mirror of https://github.com/lidarr/Lidarr
New: Quality Preferred Size Setting
Co-authored-by: Qstick <qstick@gmail.com> (cherry picked from commit d08f33ae213bb5a94b6b6aa8f6f1e780a7a9835f) Fixed: Include preferred size in quality definition reset (cherry picked from commit 8e925ac76d2f46cf5fef1ea62a20ae5e85d3000e)
This commit is contained in:
parent
6d79b5ab9a
commit
c180c327d4
|
@ -31,7 +31,7 @@
|
||||||
background-color: var(--sliderAccentColor);
|
background-color: var(--sliderAccentColor);
|
||||||
box-shadow: 0 0 0 #000;
|
box-shadow: 0 0 0 #000;
|
||||||
|
|
||||||
&:nth-child(odd) {
|
&:nth-child(3n+1) {
|
||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
.kilobitsPerSecond {
|
.kilobitsPerSecond {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex: 0 0 250px;
|
flex: 0 0 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sizeInput {
|
.sizeInput {
|
||||||
|
|
|
@ -50,21 +50,24 @@ class QualityDefinition extends Component {
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
sliderMinSize: getSliderValue(props.minSize, slider.min),
|
sliderMinSize: getSliderValue(props.minSize, slider.min),
|
||||||
sliderMaxSize: getSliderValue(props.maxSize, slider.max)
|
sliderMaxSize: getSliderValue(props.maxSize, slider.max),
|
||||||
|
sliderPreferredSize: getSliderValue(props.preferredSize, (slider.max - 3))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onSliderChange = ([sliderMinSize, sliderMaxSize]) => {
|
onSliderChange = ([sliderMinSize, sliderPreferredSize, sliderMaxSize]) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
sliderMinSize,
|
sliderMinSize,
|
||||||
sliderMaxSize
|
sliderMaxSize,
|
||||||
|
sliderPreferredSize
|
||||||
});
|
});
|
||||||
|
|
||||||
this.props.onSizeChange({
|
this.props.onSizeChange({
|
||||||
minSize: roundNumber(Math.pow(sliderMinSize, 1.1)),
|
minSize: roundNumber(Math.pow(sliderMinSize, 1.1)),
|
||||||
|
preferredSize: sliderPreferredSize === (slider.max - 3) ? null : roundNumber(Math.pow(sliderPreferredSize, 1.1)),
|
||||||
maxSize: sliderMaxSize === slider.max ? null : roundNumber(Math.pow(sliderMaxSize, 1.1))
|
maxSize: sliderMaxSize === slider.max ? null : roundNumber(Math.pow(sliderMaxSize, 1.1))
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -72,12 +75,14 @@ class QualityDefinition extends Component {
|
||||||
onAfterSliderChange = () => {
|
onAfterSliderChange = () => {
|
||||||
const {
|
const {
|
||||||
minSize,
|
minSize,
|
||||||
maxSize
|
maxSize,
|
||||||
|
preferredSize
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
sliderMiSize: getSliderValue(minSize, slider.min),
|
sliderMiSize: getSliderValue(minSize, slider.min),
|
||||||
sliderMaxSize: getSliderValue(maxSize, slider.max)
|
sliderMaxSize: getSliderValue(maxSize, slider.max),
|
||||||
|
sliderPreferredSize: getSliderValue(preferredSize, (slider.max - 3)) // fix
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +95,22 @@ class QualityDefinition extends Component {
|
||||||
|
|
||||||
this.props.onSizeChange({
|
this.props.onSizeChange({
|
||||||
minSize,
|
minSize,
|
||||||
maxSize: this.props.maxSize
|
maxSize: this.props.maxSize,
|
||||||
|
preferredSize: this.props.preferredSize
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onPreferredSizeChange = ({ value }) => {
|
||||||
|
const preferredSize = value === (MAX - 3) ? null : getValue(value);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
sliderPreferredSize: getSliderValue(preferredSize, slider.preferred)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.props.onSizeChange({
|
||||||
|
minSize: this.props.minSize,
|
||||||
|
maxSize: this.props.maxSize,
|
||||||
|
preferredSize
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,7 +123,8 @@ class QualityDefinition extends Component {
|
||||||
|
|
||||||
this.props.onSizeChange({
|
this.props.onSizeChange({
|
||||||
minSize: this.props.minSize,
|
minSize: this.props.minSize,
|
||||||
maxSize
|
maxSize,
|
||||||
|
preferredSize: this.props.preferredSize
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,20 +138,25 @@ class QualityDefinition extends Component {
|
||||||
title,
|
title,
|
||||||
minSize,
|
minSize,
|
||||||
maxSize,
|
maxSize,
|
||||||
|
preferredSize,
|
||||||
advancedSettings,
|
advancedSettings,
|
||||||
onTitleChange
|
onTitleChange
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
sliderMinSize,
|
sliderMinSize,
|
||||||
sliderMaxSize
|
sliderMaxSize,
|
||||||
|
sliderPreferredSize
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const minBytes = minSize * 128;
|
const minBytes = minSize * 128;
|
||||||
const maxBytes = maxSize && maxSize * 128;
|
|
||||||
|
|
||||||
const minRate = `${formatBytes(minBytes, true)}/s`;
|
const minRate = `${formatBytes(minBytes, true)}/s`;
|
||||||
const maxRate = maxBytes ? `${formatBytes(maxBytes, true)}/s` : 'Unlimited';
|
|
||||||
|
const preferredBytes = preferredSize * 128;
|
||||||
|
const preferredRate = preferredBytes ? `${formatBytes(preferredBytes, true)}/s` : translate('Unlimited');
|
||||||
|
|
||||||
|
const maxBytes = maxSize && maxSize * 128;
|
||||||
|
const maxRate = maxBytes ? `${formatBytes(maxBytes, true)}/s` : translate('Unlimited');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.qualityDefinition}>
|
<div className={styles.qualityDefinition}>
|
||||||
|
@ -151,9 +177,10 @@ class QualityDefinition extends Component {
|
||||||
min={slider.min}
|
min={slider.min}
|
||||||
max={slider.max}
|
max={slider.max}
|
||||||
step={slider.step}
|
step={slider.step}
|
||||||
minDistance={MIN_DISTANCE * 5}
|
minDistance={3}
|
||||||
value={[sliderMinSize, sliderMaxSize]}
|
value={[sliderMinSize, sliderPreferredSize, sliderMaxSize]}
|
||||||
withTracks={true}
|
withTracks={true}
|
||||||
|
allowCross={false}
|
||||||
snapDragDisabled={true}
|
snapDragDisabled={true}
|
||||||
className={styles.slider}
|
className={styles.slider}
|
||||||
trackClassName={styles.bar}
|
trackClassName={styles.bar}
|
||||||
|
@ -172,7 +199,23 @@ class QualityDefinition extends Component {
|
||||||
body={
|
body={
|
||||||
<QualityDefinitionLimits
|
<QualityDefinitionLimits
|
||||||
bytes={minBytes}
|
bytes={minBytes}
|
||||||
message={translate('NoMinimumForAnyRuntime')}
|
message={translate('NoMinimumForAnyDuration')}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
position={tooltipPositions.BOTTOM}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Popover
|
||||||
|
anchor={
|
||||||
|
<Label kind={kinds.SUCCESS}>{preferredRate}</Label>
|
||||||
|
}
|
||||||
|
title={translate('PreferredSize')}
|
||||||
|
body={
|
||||||
|
<QualityDefinitionLimits
|
||||||
|
bytes={preferredBytes}
|
||||||
|
message={translate('NoLimitForAnyDuration')}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
position={tooltipPositions.BOTTOM}
|
position={tooltipPositions.BOTTOM}
|
||||||
|
@ -188,7 +231,7 @@ class QualityDefinition extends Component {
|
||||||
body={
|
body={
|
||||||
<QualityDefinitionLimits
|
<QualityDefinitionLimits
|
||||||
bytes={maxBytes}
|
bytes={maxBytes}
|
||||||
message={translate('NoLimitForAnyRuntime')}
|
message={translate('NoLimitForAnyDuration')}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
position={tooltipPositions.BOTTOM}
|
position={tooltipPositions.BOTTOM}
|
||||||
|
@ -201,14 +244,14 @@ class QualityDefinition extends Component {
|
||||||
advancedSettings &&
|
advancedSettings &&
|
||||||
<div className={styles.kilobitsPerSecond}>
|
<div className={styles.kilobitsPerSecond}>
|
||||||
<div>
|
<div>
|
||||||
Min
|
{translate('Min')}
|
||||||
|
|
||||||
<NumberInput
|
<NumberInput
|
||||||
className={styles.sizeInput}
|
className={styles.sizeInput}
|
||||||
name={`${id}.min`}
|
name={`${id}.min`}
|
||||||
value={minSize || MIN}
|
value={minSize || MIN}
|
||||||
min={MIN}
|
min={MIN}
|
||||||
max={maxSize ? maxSize - MIN_DISTANCE : MAX - MIN_DISTANCE}
|
max={preferredSize ? preferredSize - 5 : MAX - 5}
|
||||||
step={0.1}
|
step={0.1}
|
||||||
isFloat={true}
|
isFloat={true}
|
||||||
onChange={this.onMinSizeChange}
|
onChange={this.onMinSizeChange}
|
||||||
|
@ -216,7 +259,22 @@ class QualityDefinition extends Component {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
Max
|
{translate('Preferred')}
|
||||||
|
|
||||||
|
<NumberInput
|
||||||
|
className={styles.sizeInput}
|
||||||
|
name={`${id}.min`}
|
||||||
|
value={preferredSize || MAX - 5}
|
||||||
|
min={MIN}
|
||||||
|
max={maxSize ? maxSize - 5 : MAX - 5}
|
||||||
|
step={0.1}
|
||||||
|
isFloat={true}
|
||||||
|
onChange={this.onPreferredSizeChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{translate('Max')}
|
||||||
|
|
||||||
<NumberInput
|
<NumberInput
|
||||||
className={styles.sizeInput}
|
className={styles.sizeInput}
|
||||||
|
@ -242,6 +300,7 @@ QualityDefinition.propTypes = {
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
minSize: PropTypes.number,
|
minSize: PropTypes.number,
|
||||||
maxSize: PropTypes.number,
|
maxSize: PropTypes.number,
|
||||||
|
preferredSize: PropTypes.number,
|
||||||
advancedSettings: PropTypes.bool.isRequired,
|
advancedSettings: PropTypes.bool.isRequired,
|
||||||
onTitleChange: PropTypes.func.isRequired,
|
onTitleChange: PropTypes.func.isRequired,
|
||||||
onSizeChange: PropTypes.func.isRequired
|
onSizeChange: PropTypes.func.isRequired
|
||||||
|
|
|
@ -23,11 +23,12 @@ class QualityDefinitionConnector extends Component {
|
||||||
this.props.setQualityDefinitionValue({ id: this.props.id, name: 'title', value });
|
this.props.setQualityDefinitionValue({ id: this.props.id, name: 'title', value });
|
||||||
};
|
};
|
||||||
|
|
||||||
onSizeChange = ({ minSize, maxSize }) => {
|
onSizeChange = ({ minSize, maxSize, preferredSize }) => {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
minSize: currentMinSize,
|
minSize: currentMinSize,
|
||||||
maxSize: currentMaxSize
|
maxSize: currentMaxSize,
|
||||||
|
preferredSize: currentPreferredSize
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (minSize !== currentMinSize) {
|
if (minSize !== currentMinSize) {
|
||||||
|
@ -37,6 +38,10 @@ class QualityDefinitionConnector extends Component {
|
||||||
if (maxSize !== currentMaxSize) {
|
if (maxSize !== currentMaxSize) {
|
||||||
this.props.setQualityDefinitionValue({ id, name: 'maxSize', value: maxSize });
|
this.props.setQualityDefinitionValue({ id, name: 'maxSize', value: maxSize });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preferredSize !== currentPreferredSize) {
|
||||||
|
this.props.setQualityDefinitionValue({ id, name: 'preferredSize', value: preferredSize });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -57,6 +62,7 @@ QualityDefinitionConnector.propTypes = {
|
||||||
id: PropTypes.number.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
minSize: PropTypes.number,
|
minSize: PropTypes.number,
|
||||||
maxSize: PropTypes.number,
|
maxSize: PropTypes.number,
|
||||||
|
preferredSize: PropTypes.number,
|
||||||
setQualityDefinitionValue: PropTypes.func.isRequired,
|
setQualityDefinitionValue: PropTypes.func.isRequired,
|
||||||
clearPendingChanges: PropTypes.func.isRequired
|
clearPendingChanges: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Lidarr.Api.V1.Qualities
|
||||||
|
|
||||||
public double? MinSize { get; set; }
|
public double? MinSize { get; set; }
|
||||||
public double? MaxSize { get; set; }
|
public double? MaxSize { get; set; }
|
||||||
|
public double? PreferredSize { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class QualityDefinitionResourceMapper
|
public static class QualityDefinitionResourceMapper
|
||||||
|
@ -33,7 +34,8 @@ namespace Lidarr.Api.V1.Qualities
|
||||||
Title = model.Title,
|
Title = model.Title,
|
||||||
Weight = model.Weight,
|
Weight = model.Weight,
|
||||||
MinSize = model.MinSize,
|
MinSize = model.MinSize,
|
||||||
MaxSize = model.MaxSize
|
MaxSize = model.MaxSize,
|
||||||
|
PreferredSize = model.PreferredSize
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +53,8 @@ namespace Lidarr.Api.V1.Qualities
|
||||||
Title = resource.Title,
|
Title = resource.Title,
|
||||||
Weight = resource.Weight,
|
Weight = resource.Weight,
|
||||||
MinSize = resource.MinSize,
|
MinSize = resource.MinSize,
|
||||||
MaxSize = resource.MaxSize
|
MaxSize = resource.MaxSize,
|
||||||
|
PreferredSize = resource.PreferredSize
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,30 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
GivenPreferredDownloadProtocol(DownloadProtocol.Usenet);
|
GivenPreferredDownloadProtocol(DownloadProtocol.Usenet);
|
||||||
|
|
||||||
|
Mocker.GetMock<IQualityDefinitionService>()
|
||||||
|
.Setup(s => s.Get(It.IsAny<Quality>()))
|
||||||
|
.Returns(new QualityDefinition { PreferredSize = null });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenPreferredSize(double? size)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IQualityDefinitionService>()
|
||||||
|
.Setup(s => s.Get(It.IsAny<Quality>()))
|
||||||
|
.Returns(new QualityDefinition { PreferredSize = size });
|
||||||
}
|
}
|
||||||
|
|
||||||
private Album GivenAlbum(int id)
|
private Album GivenAlbum(int id)
|
||||||
{
|
{
|
||||||
|
var release = Builder<AlbumRelease>.CreateNew()
|
||||||
|
.With(e => e.AlbumId = id)
|
||||||
|
.With(e => e.Monitored = true)
|
||||||
|
.With(e => e.Duration = 3600000)
|
||||||
|
.Build();
|
||||||
|
|
||||||
return Builder<Album>.CreateNew()
|
return Builder<Album>.CreateNew()
|
||||||
.With(e => e.Id = id)
|
.With(e => e.Id = id)
|
||||||
|
.With(e => e.AlbumReleases = new List<AlbumRelease> { release })
|
||||||
.Build();
|
.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +148,44 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbumHdLargeYoung);
|
qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbumHdLargeYoung);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_order_by_closest_to_preferred_size_if_both_under()
|
||||||
|
{
|
||||||
|
// 1000 Kibit/Sec * 60 Min Duration = 439.5 MiB
|
||||||
|
GivenPreferredSize(1000);
|
||||||
|
|
||||||
|
var remoteAlbumSmall = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 120.Megabytes(), age: 1);
|
||||||
|
var remoteAlbumLarge = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 400.Megabytes(), age: 1);
|
||||||
|
|
||||||
|
var decisions = new List<DownloadDecision>();
|
||||||
|
decisions.Add(new DownloadDecision(remoteAlbumSmall));
|
||||||
|
decisions.Add(new DownloadDecision(remoteAlbumLarge));
|
||||||
|
|
||||||
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
|
qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbumLarge);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_order_by_closest_to_preferred_size_if_preferred_is_in_between()
|
||||||
|
{
|
||||||
|
// 700 Kibit/Sec * 60 Min Duration = 307.6 MiB
|
||||||
|
GivenPreferredSize(700);
|
||||||
|
|
||||||
|
var remoteAlbum1 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 100.Megabytes(), age: 1);
|
||||||
|
var remoteAlbum2 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 200.Megabytes(), age: 1);
|
||||||
|
var remoteAlbum3 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 300.Megabytes(), age: 1);
|
||||||
|
var remoteAlbum4 = GivenRemoteAlbum(new List<Album> { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 500.Megabytes(), age: 1);
|
||||||
|
|
||||||
|
var decisions = new List<DownloadDecision>();
|
||||||
|
decisions.Add(new DownloadDecision(remoteAlbum1));
|
||||||
|
decisions.Add(new DownloadDecision(remoteAlbum2));
|
||||||
|
decisions.Add(new DownloadDecision(remoteAlbum3));
|
||||||
|
decisions.Add(new DownloadDecision(remoteAlbum4));
|
||||||
|
|
||||||
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
|
qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbum3);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_order_by_youngest()
|
public void should_order_by_youngest()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(075)]
|
||||||
|
public class quality_definition_preferred_size : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("QualityDefinitions").AddColumn("PreferredSize").AsDouble().Nullable();
|
||||||
|
|
||||||
|
Execute.Sql("UPDATE \"QualityDefinitions\" SET \"PreferredSize\" = \"MaxSize\" - 5 WHERE \"MaxSize\" > 5");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,14 +13,16 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly IDelayProfileService _delayProfileService;
|
private readonly IDelayProfileService _delayProfileService;
|
||||||
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
|
|
||||||
public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y);
|
public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y);
|
||||||
public delegate int CompareDelegate<TSubject, TValue>(DownloadDecision x, DownloadDecision y);
|
public delegate int CompareDelegate<TSubject, TValue>(DownloadDecision x, DownloadDecision y);
|
||||||
|
|
||||||
public DownloadDecisionComparer(IConfigService configService, IDelayProfileService delayProfileService)
|
public DownloadDecisionComparer(IConfigService configService, IDelayProfileService delayProfileService, IQualityDefinitionService qualityDefinitionService)
|
||||||
{
|
{
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_delayProfileService = delayProfileService;
|
_delayProfileService = delayProfileService;
|
||||||
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Compare(DownloadDecision x, DownloadDecision y)
|
public int Compare(DownloadDecision x, DownloadDecision y)
|
||||||
|
@ -166,8 +168,27 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
|
|
||||||
private int CompareSize(DownloadDecision x, DownloadDecision y)
|
private int CompareSize(DownloadDecision x, DownloadDecision y)
|
||||||
{
|
{
|
||||||
// TODO: Is smaller better? Smaller for usenet could mean no par2 files.
|
var sizeCompare = CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum =>
|
||||||
return CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.Release.Size.Round(200.Megabytes()));
|
{
|
||||||
|
var preferredSize = _qualityDefinitionService.Get(remoteAlbum.ParsedAlbumInfo.Quality.Quality).PreferredSize;
|
||||||
|
|
||||||
|
var releaseDuration = remoteAlbum.Albums.Select(a => a.AlbumReleases.Value.Where(r => r.Monitored || a.AnyReleaseOk).Select(r => r.Duration).MaxOrDefault()).Sum() / 1000;
|
||||||
|
|
||||||
|
// If no value for preferred it means unlimited so fallback to sort largest is best
|
||||||
|
if (preferredSize.HasValue && releaseDuration > 0)
|
||||||
|
{
|
||||||
|
var preferredAlbumSize = releaseDuration * preferredSize.Value.Kilobits();
|
||||||
|
|
||||||
|
// Calculate closest to the preferred size
|
||||||
|
return Math.Abs((remoteAlbum.Release.Size - preferredAlbumSize).Round(100.Megabytes())) * (-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return remoteAlbum.Release.Size.Round(100.Megabytes());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return sizeCompare;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Profiles.Delay;
|
using NzbDrone.Core.Profiles.Delay;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
|
@ -14,11 +15,13 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly IDelayProfileService _delayProfileService;
|
private readonly IDelayProfileService _delayProfileService;
|
||||||
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
|
|
||||||
public DownloadDecisionPriorizationService(IConfigService configService, IDelayProfileService delayProfileService)
|
public DownloadDecisionPriorizationService(IConfigService configService, IDelayProfileService delayProfileService, IQualityDefinitionService qualityDefinitionService)
|
||||||
{
|
{
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_delayProfileService = delayProfileService;
|
_delayProfileService = delayProfileService;
|
||||||
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
|
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
|
||||||
|
@ -26,7 +29,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
return decisions.Where(c => c.RemoteAlbum.DownloadAllowed)
|
return decisions.Where(c => c.RemoteAlbum.DownloadAllowed)
|
||||||
.GroupBy(c => c.RemoteAlbum.Artist.Id, (artistId, downloadDecisions) =>
|
.GroupBy(c => c.RemoteAlbum.Artist.Id, (artistId, downloadDecisions) =>
|
||||||
{
|
{
|
||||||
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_configService, _delayProfileService));
|
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_configService, _delayProfileService, _qualityDefinitionService));
|
||||||
})
|
})
|
||||||
.SelectMany(c => c)
|
.SelectMany(c => c)
|
||||||
.Union(decisions.Where(c => !c.RemoteAlbum.DownloadAllowed))
|
.Union(decisions.Where(c => !c.RemoteAlbum.DownloadAllowed))
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
var minSize = qualityDefinition.MinSize.Value.Kilobits();
|
var minSize = qualityDefinition.MinSize.Value.Kilobits();
|
||||||
|
|
||||||
// Multiply minSize by smallest release duration
|
// Multiply minSize by smallest release duration
|
||||||
minSize = minSize * minReleaseDuration;
|
minSize *= minReleaseDuration;
|
||||||
|
|
||||||
// If the parsed size is smaller than minSize we don't want it
|
// If the parsed size is smaller than minSize we don't want it
|
||||||
if (subject.Release.Size < minSize)
|
if (subject.Release.Size < minSize)
|
||||||
|
@ -75,7 +75,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
var maxSize = qualityDefinition.MaxSize.Value.Kilobits();
|
var maxSize = qualityDefinition.MaxSize.Value.Kilobits();
|
||||||
|
|
||||||
// Multiply maxSize by Album.Duration
|
// Multiply maxSize by Album.Duration
|
||||||
maxSize = maxSize * maxReleaseDuration;
|
maxSize *= maxReleaseDuration;
|
||||||
|
|
||||||
// If the parsed size is greater than maxSize we don't want it
|
// If the parsed size is greater than maxSize we don't want it
|
||||||
if (subject.Release.Size > maxSize)
|
if (subject.Release.Size > maxSize)
|
||||||
|
|
|
@ -680,9 +680,9 @@
|
||||||
"NoImportListsFound": "No import lists found",
|
"NoImportListsFound": "No import lists found",
|
||||||
"NoIndexersFound": "No indexers found",
|
"NoIndexersFound": "No indexers found",
|
||||||
"NoLeaveIt": "No, Leave It",
|
"NoLeaveIt": "No, Leave It",
|
||||||
"NoLimitForAnyRuntime": "No limit for any runtime",
|
"NoLimitForAnyDuration": "No limit for any duration",
|
||||||
"NoLogFiles": "No log files",
|
"NoLogFiles": "No log files",
|
||||||
"NoMinimumForAnyRuntime": "No minimum for any runtime",
|
"NoMinimumForAnyDuration": "No minimum for any duration",
|
||||||
"NoMissingItems": "No missing items",
|
"NoMissingItems": "No missing items",
|
||||||
"NoResultsFound": "No results found",
|
"NoResultsFound": "No results found",
|
||||||
"NoTagsHaveBeenAddedYet": "No tags have been added yet",
|
"NoTagsHaveBeenAddedYet": "No tags have been added yet",
|
||||||
|
@ -754,6 +754,7 @@
|
||||||
"PreferTorrent": "Prefer Torrent",
|
"PreferTorrent": "Prefer Torrent",
|
||||||
"PreferUsenet": "Prefer Usenet",
|
"PreferUsenet": "Prefer Usenet",
|
||||||
"PreferredProtocol": "Preferred Protocol",
|
"PreferredProtocol": "Preferred Protocol",
|
||||||
|
"PreferredSize": "Preferred Size",
|
||||||
"Presets": "Presets",
|
"Presets": "Presets",
|
||||||
"PreviewRename": "Preview Rename",
|
"PreviewRename": "Preview Rename",
|
||||||
"PreviewRetag": "Preview Retag",
|
"PreviewRetag": "Preview Retag",
|
||||||
|
@ -1116,6 +1117,7 @@
|
||||||
"UnableToLoadTheCalendar": "Unable to load the calendar",
|
"UnableToLoadTheCalendar": "Unable to load the calendar",
|
||||||
"UnableToLoadUISettings": "Unable to load UI settings",
|
"UnableToLoadUISettings": "Unable to load UI settings",
|
||||||
"Ungroup": "Ungroup",
|
"Ungroup": "Ungroup",
|
||||||
|
"Unlimited": "Unlimited",
|
||||||
"UnmappedFiles": "Unmapped Files",
|
"UnmappedFiles": "Unmapped Files",
|
||||||
"UnmappedFilesOnly": "Unmapped Files Only",
|
"UnmappedFilesOnly": "Unmapped Files Only",
|
||||||
"Unmonitored": "Unmonitored",
|
"Unmonitored": "Unmonitored",
|
||||||
|
|
|
@ -161,44 +161,44 @@ namespace NzbDrone.Core.Qualities
|
||||||
|
|
||||||
DefaultQualityDefinitions = new HashSet<QualityDefinition>
|
DefaultQualityDefinitions = new HashSet<QualityDefinition>
|
||||||
{
|
{
|
||||||
new QualityDefinition(Quality.Unknown) { Weight = 1, MinSize = 0, MaxSize = 350, GroupWeight = 1 },
|
new QualityDefinition(Quality.Unknown) { Weight = 1, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupWeight = 1 },
|
||||||
new QualityDefinition(Quality.MP3_008) { Weight = 2, MinSize = 0, MaxSize = 10, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_008) { Weight = 2, MinSize = 0, MaxSize = 10, PreferredSize = 5, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_016) { Weight = 3, MinSize = 0, MaxSize = 20, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_016) { Weight = 3, MinSize = 0, MaxSize = 20, PreferredSize = 15, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_024) { Weight = 4, MinSize = 0, MaxSize = 30, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_024) { Weight = 4, MinSize = 0, MaxSize = 30, PreferredSize = 25, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_032) { Weight = 5, MinSize = 0, MaxSize = 40, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_032) { Weight = 5, MinSize = 0, MaxSize = 40, PreferredSize = 35, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_040) { Weight = 6, MinSize = 0, MaxSize = 45, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_040) { Weight = 6, MinSize = 0, MaxSize = 45, PreferredSize = 40, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_048) { Weight = 7, MinSize = 0, MaxSize = 55, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_048) { Weight = 7, MinSize = 0, MaxSize = 55, PreferredSize = 50, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_056) { Weight = 8, MinSize = 0, MaxSize = 65, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_056) { Weight = 8, MinSize = 0, MaxSize = 65, PreferredSize = 60, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_064) { Weight = 9, MinSize = 0, MaxSize = 75, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_064) { Weight = 9, MinSize = 0, MaxSize = 75, PreferredSize = 70, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_080) { Weight = 10, MinSize = 0, MaxSize = 95, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
new QualityDefinition(Quality.MP3_080) { Weight = 10, MinSize = 0, MaxSize = 95, PreferredSize = 90, GroupName = "Trash Quality Lossy", GroupWeight = 2 },
|
||||||
new QualityDefinition(Quality.MP3_096) { Weight = 11, MinSize = 0, MaxSize = 110, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
new QualityDefinition(Quality.MP3_096) { Weight = 11, MinSize = 0, MaxSize = 110, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
||||||
new QualityDefinition(Quality.MP3_112) { Weight = 12, MinSize = 0, MaxSize = 125, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
new QualityDefinition(Quality.MP3_112) { Weight = 12, MinSize = 0, MaxSize = 125, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
||||||
new QualityDefinition(Quality.MP3_128) { Weight = 13, MinSize = 0, MaxSize = 140, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
new QualityDefinition(Quality.MP3_128) { Weight = 13, MinSize = 0, MaxSize = 140, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
||||||
new QualityDefinition(Quality.VORBIS_Q5) { Weight = 14, MinSize = 0, MaxSize = 175, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
new QualityDefinition(Quality.VORBIS_Q5) { Weight = 14, MinSize = 0, MaxSize = 175, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
||||||
new QualityDefinition(Quality.MP3_160) { Weight = 14, MinSize = 0, MaxSize = 175, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
new QualityDefinition(Quality.MP3_160) { Weight = 14, MinSize = 0, MaxSize = 175, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 },
|
||||||
new QualityDefinition(Quality.MP3_192) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
new QualityDefinition(Quality.MP3_192) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
||||||
new QualityDefinition(Quality.VORBIS_Q6) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
new QualityDefinition(Quality.VORBIS_Q6) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
||||||
new QualityDefinition(Quality.AAC_192) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
new QualityDefinition(Quality.AAC_192) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
||||||
new QualityDefinition(Quality.WMA) { Weight = 15, MinSize = 0, MaxSize = 350, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
new QualityDefinition(Quality.WMA) { Weight = 15, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
||||||
new QualityDefinition(Quality.MP3_224) { Weight = 16, MinSize = 0, MaxSize = 245, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
new QualityDefinition(Quality.MP3_224) { Weight = 16, MinSize = 0, MaxSize = 245, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 },
|
||||||
new QualityDefinition(Quality.VORBIS_Q7) { Weight = 17, MinSize = 0, MaxSize = 245, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
new QualityDefinition(Quality.VORBIS_Q7) { Weight = 17, MinSize = 0, MaxSize = 245, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
||||||
new QualityDefinition(Quality.MP3_VBR_V2) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
new QualityDefinition(Quality.MP3_VBR_V2) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
||||||
new QualityDefinition(Quality.MP3_256) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
new QualityDefinition(Quality.MP3_256) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
||||||
new QualityDefinition(Quality.VORBIS_Q8) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
new QualityDefinition(Quality.VORBIS_Q8) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
||||||
new QualityDefinition(Quality.AAC_256) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
new QualityDefinition(Quality.AAC_256) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 },
|
||||||
new QualityDefinition(Quality.MP3_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
new QualityDefinition(Quality.MP3_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
||||||
new QualityDefinition(Quality.AAC_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
new QualityDefinition(Quality.AAC_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
||||||
new QualityDefinition(Quality.MP3_320) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
new QualityDefinition(Quality.MP3_320) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
||||||
new QualityDefinition(Quality.VORBIS_Q9) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
new QualityDefinition(Quality.VORBIS_Q9) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
||||||
new QualityDefinition(Quality.AAC_320) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
new QualityDefinition(Quality.AAC_320) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
||||||
new QualityDefinition(Quality.VORBIS_Q10) { Weight = 21, MinSize = 0, MaxSize = 550, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
new QualityDefinition(Quality.VORBIS_Q10) { Weight = 21, MinSize = 0, MaxSize = 550, PreferredSize = 295, GroupName = "High Quality Lossy", GroupWeight = 6 },
|
||||||
new QualityDefinition(Quality.FLAC) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 },
|
new QualityDefinition(Quality.FLAC) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 },
|
||||||
new QualityDefinition(Quality.ALAC) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 },
|
new QualityDefinition(Quality.ALAC) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 },
|
||||||
new QualityDefinition(Quality.APE) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 },
|
new QualityDefinition(Quality.APE) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 },
|
||||||
new QualityDefinition(Quality.WAVPACK) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 },
|
new QualityDefinition(Quality.WAVPACK) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 },
|
||||||
new QualityDefinition(Quality.FLAC_24) { Weight = 23, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 },
|
new QualityDefinition(Quality.FLAC_24) { Weight = 23, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 },
|
||||||
new QualityDefinition(Quality.ALAC_24) { Weight = 23, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 },
|
new QualityDefinition(Quality.ALAC_24) { Weight = 23, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 },
|
||||||
new QualityDefinition(Quality.WAV) { Weight = 24, MinSize = 0, MaxSize = null, GroupWeight = 8 }
|
new QualityDefinition(Quality.WAV) { Weight = 24, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupWeight = 8 }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace NzbDrone.Core.Qualities
|
||||||
|
|
||||||
public double? MinSize { get; set; }
|
public double? MinSize { get; set; }
|
||||||
public double? MaxSize { get; set; }
|
public double? MaxSize { get; set; }
|
||||||
|
public double? PreferredSize { get; set; }
|
||||||
|
|
||||||
public QualityDefinition()
|
public QualityDefinition()
|
||||||
{
|
{
|
||||||
|
|
|
@ -121,6 +121,7 @@ namespace NzbDrone.Core.Qualities
|
||||||
|
|
||||||
existing.MinSize = definition.MinSize;
|
existing.MinSize = definition.MinSize;
|
||||||
existing.MaxSize = definition.MaxSize;
|
existing.MaxSize = definition.MaxSize;
|
||||||
|
existing.PreferredSize = definition.PreferredSize;
|
||||||
existing.Title = message.ResetTitles ? definition.Title : existing.Title;
|
existing.Title = message.ResetTitles ? definition.Title : existing.Title;
|
||||||
|
|
||||||
updateList.Add(existing);
|
updateList.Add(existing);
|
||||||
|
|
Loading…
Reference in New Issue