Fixed: Split concatenated authors when calculating match

pull/1205/head
ta264 3 years ago
parent 17535bd8d6
commit cdf8b0bc8f

@ -0,0 +1,95 @@
using System.Collections.Generic;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles.BookImport.Identification;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MediaFiles.BookImport.Identification
{
[TestFixture]
public class DistanceCalculatorFixture : TestBase
{
[Test]
public void should_reverse_single_reversed_author()
{
var input = new List<string> { "Last, First" };
var authors = DistanceCalculator.GetAuthorVariants(input);
authors.Should().Contain("First Last");
}
[Test]
public void should_reverse_two_reversed_author()
{
var input = new List<string>
{
"Last, First",
"Last2, First2"
};
var authors = DistanceCalculator.GetAuthorVariants(input);
authors.Should().HaveCount(4);
authors.Should().Contain("First Last");
authors.Should().Contain("First2 Last2");
authors.Should().Contain("Last, First");
authors.Should().Contain("Last2, First2");
}
[Test]
public void should_not_reverse_single_author()
{
var input = new List<string> { "First Last" };
var authors = DistanceCalculator.GetAuthorVariants(input);
authors.Should().HaveCount(1);
authors.Should().Contain("First Last");
}
[TestCase("First1 Last1, First2 Last2", "First1 Last1", "First2 Last2")]
[TestCase("First1 Last1; First2 Last2", "First1 Last1", "First2 Last2")]
[TestCase("First1 Last1 & First2 Last2", "First1 Last1", "First2 Last2")]
[TestCase("First1 Last1 / First2 Last2", "First1 Last1", "First2 Last2")]
[TestCase("First1 Last1 and First2 Last2", "First1 Last1", "First2 Last2")]
public void should_split_concatenated_author(string inputString, string first, string second)
{
var input = new List<string> { inputString };
var authors = DistanceCalculator.GetAuthorVariants(input);
authors.Should().Contain(inputString);
authors.Should().Contain(first);
authors.Should().Contain(second);
authors.Should().HaveCount(3);
}
[Test]
public void should_split_concatenated_with_trailing_and()
{
var inputString = "First Last, First2 Last2 & First3 Last3";
var input = new List<string> { inputString };
var authors = DistanceCalculator.GetAuthorVariants(input);
authors.Should().Contain(inputString);
authors.Should().Contain("First Last");
authors.Should().Contain("First2 Last2");
authors.Should().Contain("First3 Last3");
authors.Should().HaveCount(4);
}
[Test]
public void should_not_split_if_multiple_input()
{
var input = new List<string>
{
"First Last",
"Second Third, Fourth Fifth"
};
var authors = DistanceCalculator.GetAuthorVariants(input);
authors.Should().HaveCount(2);
authors.Should().Contain("First Last");
authors.Should().Contain("Second Third, Fourth Fifth");
}
}
}

@ -85,7 +85,7 @@ namespace NzbDrone.Core.MediaFiles
authors.AddRange(tag.PerformersSort);
}
BookAuthors = authors.ToArray();
BookAuthors = authors.Distinct().ToArray();
Track = tag.Track;
TrackCount = tag.TrackCount;
Book = tag.Album ?? tag.AlbumSort;

@ -130,7 +130,7 @@ namespace NzbDrone.Core.MediaFiles.BookImport.Identification
{
// Sort by most voted so less likely to swap to a random release
return GetDbCandidatesByEdition(_editionService.GetEditionsByBook(book.Id)
.OrderByDescending(x => x.Ratings.Votes)
.OrderByDescending(x => x.Ratings.Popularity)
.ToList(), includeExisting);
}
@ -171,7 +171,9 @@ namespace NzbDrone.Core.MediaFiles.BookImport.Identification
var authorTags = localEdition.LocalBooks.MostCommon(x => x.FileTrackInfo.Authors) ?? new List<string>();
if (authorTags.Any())
{
foreach (var authorTag in authorTags)
var variants = DistanceCalculator.GetAuthorVariants(authorTags.Where(x => x.IsNotNullOrWhiteSpace()).ToList());
foreach (var authorTag in variants)
{
if (authorTag.IsNotNullOrWhiteSpace())
{

@ -30,15 +30,7 @@ namespace NzbDrone.Core.MediaFiles.BookImport.Identification
.First()
.First();
var authors = new List<string>(fileAuthors);
foreach (var author in fileAuthors)
{
if (author.Contains(','))
{
authors.Add(authors[0].Split(',', 2).Select(x => x.Trim()).Reverse().ConcatToString(" "));
}
}
var authors = GetAuthorVariants(fileAuthors);
dist.AddString("author", authors, edition.Book.Value.AuthorMetadata.Value.Name);
Logger.Trace("author: '{0}' vs '{1}'; {2}", authors.ConcatToString("' or '"), edition.Book.Value.AuthorMetadata.Value.Name, dist.NormalizedDistance());
@ -115,5 +107,75 @@ namespace NzbDrone.Core.MediaFiles.BookImport.Identification
return dist;
}
public static List<string> GetAuthorVariants(List<string> fileAuthors)
{
var authors = new List<string>(fileAuthors);
if (fileAuthors.Count == 1)
{
authors.AddRange(SplitAuthor(fileAuthors[0]));
}
foreach (var author in fileAuthors)
{
if (author.Contains(','))
{
var split = author.Split(',', 2).Select(x => x.Trim());
if (!split.First().Contains(' '))
{
authors.Add(split.Reverse().ConcatToString(" "));
}
}
}
return authors;
}
private static List<string> SplitAuthor(string input)
{
var seps = new[] { ';', '/' };
foreach (var sep in seps)
{
if (input.Contains(sep))
{
return input.Split(sep).Select(x => x.Trim()).ToList();
}
}
var andSeps = new List<string> { " and ", " & " };
foreach (var sep in andSeps)
{
if (input.Contains(sep))
{
var result = new List<string>();
foreach (var s in input.Split(sep).Select(x => x.Trim()))
{
var s2 = SplitAuthor(s);
if (s2.Any())
{
result.AddRange(s2);
}
else
{
result.Add(s);
}
}
return result;
}
}
if (input.Contains(','))
{
var split = input.Split(',').Select(x => x.Trim()).ToList();
if (split[0].Contains(' '))
{
return split;
}
}
return new List<string>();
}
}
}

Loading…
Cancel
Save