diff --git a/src/NzbDrone.Core.Test/MusicTests/TitleMatchingTests/TitleMatchingFixture.cs b/src/NzbDrone.Core.Test/MusicTests/TitleMatchingTests/TitleMatchingFixture.cs new file mode 100644 index 000000000..af429d0db --- /dev/null +++ b/src/NzbDrone.Core.Test/MusicTests/TitleMatchingTests/TitleMatchingFixture.cs @@ -0,0 +1,69 @@ +using System.Linq; +using FluentAssertions; +using NLog; +using NUnit.Framework; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Music; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.MusicTests.TitleMatchingTests +{ + [TestFixture] + public class TitleMatchingFixture : DbTest + { + private TrackRepository _trackRepository; + private TrackService _trackService; + + [SetUp] + public void Setup() + { + _trackRepository = Mocker.Resolve(); + _trackService = + new TrackService(_trackRepository, Mocker.Resolve(), Mocker.Resolve()); + + _trackRepository.Insert(new Track + { + Title = "This is the short test title", + ForeignTrackId = "this is a fake id2", + AlbumId = 4321, + AbsoluteTrackNumber = 1, + MediumNumber = 1, + TrackFileId = 1 + }); + + _trackRepository.Insert(new Track + { + Title = "This is the long test title", + ForeignTrackId = "this is a fake id", + AlbumId = 4321, + AbsoluteTrackNumber = 2, + MediumNumber = 1, + TrackFileId = 2 + }); + } + + [Test] + public void should_find_track_in_db_by_tracktitle_longer_then_relaeasetitle() + { + var track = _trackService.FindTrackByTitle(1234, 4321, 1, 1, "This is the short test title with some bla"); + + track.Title.Should().Be(_trackRepository.GetTracksByFileId(1).First().Title); + } + + [Test] + public void should_find_track_in_db_by_tracktitle_shorter_then_relaeasetitle() + { + var track = _trackService.FindTrackByTitle(1234, 4321, 1, 2, "test title"); + + track.Title.Should().Be(_trackRepository.GetTracksByFileId(2).First().Title); + } + + [Test] + public void should_not_find_track_in_db_by_wrong_title() + { + var track = _trackService.FindTrackByTitle(1234, 4321, 1, 1, "the short title"); + + track.Should().BeNull(); + } + } +} diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 48ffca301..d4922bc05 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -306,6 +306,7 @@ + diff --git a/src/NzbDrone.Core/Music/TrackService.cs b/src/NzbDrone.Core/Music/TrackService.cs index 93a36c826..445281040 100644 --- a/src/NzbDrone.Core/Music/TrackService.cs +++ b/src/NzbDrone.Core/Music/TrackService.cs @@ -79,35 +79,25 @@ namespace NzbDrone.Core.Music public Track FindTrackByTitle(int artistId, int albumId, int mediumNumber, int trackNumber, string releaseTitle) { // TODO: can replace this search mechanism with something smarter/faster/better - var normalizedReleaseTitle = Parser.Parser.NormalizeEpisodeTitle(releaseTitle).Replace(".", " "); + var normalizedReleaseTitle = Parser.Parser.NormalizeTrackTitle(releaseTitle).Replace(".", " "); var tracks = _trackRepository.GetTracksByMedium(albumId, mediumNumber); - var matches = tracks.Select( - track => new + var matches = from track in tracks + //if we have a trackNumber use it + let trackNumCheck = (trackNumber == 0 || track.AbsoluteTrackNumber == trackNumber) + //if release title is longer than track title + let posReleaseTitle = normalizedReleaseTitle.IndexOf(Parser.Parser.NormalizeTrackTitle(track.Title), StringComparison.CurrentCultureIgnoreCase) + //if track title is longer than release title + let posTrackTitle = Parser.Parser.NormalizeTrackTitle(track.Title).IndexOf(normalizedReleaseTitle, StringComparison.CurrentCultureIgnoreCase) + where track.Title.Length > 0 && trackNumCheck && (posReleaseTitle >= 0 || posTrackTitle >= 0) + orderby posReleaseTitle, posTrackTitle + select new { - Position = normalizedReleaseTitle.IndexOf(Parser.Parser.NormalizeEpisodeTitle(track.Title), StringComparison.CurrentCultureIgnoreCase), - Length = Parser.Parser.NormalizeEpisodeTitle(track.Title).Length, + NormalizedLength = Parser.Parser.NormalizeTrackTitle(track.Title).Length, Track = track - }); + }; - if (trackNumber == 0) - { - matches = matches.Where(e => e.Track.Title.Length > 0 && e.Position >= 0); - } else - { - matches = matches.Where(e => e.Track.Title.Length > 0 && e.Position >= 0 && e.Track.AbsoluteTrackNumber == trackNumber); - } - - matches.OrderBy(e => e.Position) - .ThenByDescending(e => e.Length) - .ToList(); - - if (matches.Any()) - { - return matches.First().Track; - } - - return null; + return matches.OrderByDescending(e => e.NormalizedLength).FirstOrDefault()?.Track; } public List TracksWithFiles(int artistId) diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index a349a3036..49fd8cb18 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -529,7 +529,7 @@ namespace NzbDrone.Core.Parser return NormalizeRegex.Replace(name, string.Empty).ToLower().RemoveAccent(); } - public static string NormalizeEpisodeTitle(string title) + public static string NormalizeTrackTitle(string title) { title = SpecialEpisodeWordRegex.Replace(title, string.Empty); title = PunctuationRegex.Replace(title, " ");