Fixed: Improved special episode parsing for multiple matching titles

pull/3113/head
Mark McDowall 10 years ago
parent 0adea0ded6
commit 8aa6969aee

@ -14,32 +14,50 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeServiceTests
[TestFixture] [TestFixture]
public class FindEpisodeByTitleFixture : CoreTest<EpisodeService> public class FindEpisodeByTitleFixture : CoreTest<EpisodeService>
{ {
private Episode _episode; private List<Episode> _episodes;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_episode = Builder<Episode>.CreateNew().Build(); _episodes = Builder<Episode>.CreateListOfSize(5)
.Build()
.ToList();
} }
private void GivenEpisodeTitle(string title) private void GivenEpisodesWithTitles(params string[] titles)
{ {
_episode.Title = title; for (int i = 0; i < titles.Count(); i++)
{
_episodes[i].Title = titles[i];
}
Mocker.GetMock<IEpisodeRepository>() Mocker.GetMock<IEpisodeRepository>()
.Setup(s => s.GetEpisodes(It.IsAny<int>(), It.IsAny<int>())) .Setup(s => s.GetEpisodes(It.IsAny<int>(), It.IsAny<int>()))
.Returns(new List<Episode> { _episode }); .Returns(_episodes);
} }
[Test] [Test]
public void should_find_episode_by_title() public void should_find_episode_by_title()
{ {
GivenEpisodeTitle("A Journey to the Highlands"); const string expectedTitle = "A Journey to the Highlands";
GivenEpisodesWithTitles(expectedTitle);
Subject.FindEpisodeByTitle(1, 1, "Downton.Abbey.A.Journey.To.The.Highlands.720p.BluRay.x264-aAF") Subject.FindEpisodeByTitle(1, 1, "Downton.Abbey.A.Journey.To.The.Highlands.720p.BluRay.x264-aAF")
.Title .Title
.Should() .Should()
.Be(_episode.Title); .Be(expectedTitle);
}
[Test]
public void should_prefer_longer_match()
{
const string expectedTitle = "Inside The Walking Dead: Walker University";
GivenEpisodesWithTitles("Inside The Walking Dead", expectedTitle);
Subject.FindEpisodeByTitle(1, 1, "The.Walking.Dead.S04.Special.Inside.The.Walking.Dead.Walker.University.720p.HDTV.x264-W4F")
.Title
.Should()
.Be(expectedTitle);
} }
} }
} }

@ -357,8 +357,11 @@ namespace NzbDrone.Core.Parser
public static string NormalizeEpisodeTitle(string title) public static string NormalizeEpisodeTitle(string title)
{ {
return SpecialEpisodeWordRegex.Replace(title, String.Empty) title = SpecialEpisodeWordRegex.Replace(title, String.Empty);
.Trim() title = PunctuationRegex.Replace(title, " ");
title = DuplicateSpacesRegex.Replace(title, " ");
return title.Trim()
.ToLower(); .ToLower();
} }

@ -17,7 +17,7 @@ namespace NzbDrone.Core.Tv
List<Episode> GetEpisodes(IEnumerable<Int32> ids); List<Episode> GetEpisodes(IEnumerable<Int32> ids);
Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber); Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber);
Episode FindEpisode(int seriesId, int absoluteEpisodeNumber); Episode FindEpisode(int seriesId, int absoluteEpisodeNumber);
Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string episodeTitle); Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string releaseTitle);
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber); List<Episode> FindEpisodesBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber);
Episode FindEpisodeBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber); Episode FindEpisodeBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
Episode GetEpisode(int seriesId, String date); Episode GetEpisode(int seriesId, String date);
@ -103,19 +103,25 @@ namespace NzbDrone.Core.Tv
return _episodeRepository.GetEpisodes(seriesId, seasonNumber); return _episodeRepository.GetEpisodes(seriesId, seasonNumber);
} }
public Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string episodeTitle) public Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string releaseTitle)
{ {
// TODO: can replace this search mechanism with something smarter/faster/better // TODO: can replace this search mechanism with something smarter/faster/better
var search = Parser.Parser.NormalizeEpisodeTitle(episodeTitle).Replace(".", " "); var normalizedReleaseTitle = Parser.Parser.NormalizeEpisodeTitle(releaseTitle).Replace(".", " ");
var episodes = _episodeRepository.GetEpisodes(seriesId, seasonNumber);
return _episodeRepository.GetEpisodes(seriesId, seasonNumber)
.FirstOrDefault(e => var query = episodes.Select(
{ episode => new
// normalize episode title {
var title = Parser.Parser.NormalizeEpisodeTitle(e.Title); Position = normalizedReleaseTitle.IndexOf(Parser.Parser.NormalizeEpisodeTitle(episode.Title), StringComparison.CurrentCultureIgnoreCase),
// find episode title within search string Length = Parser.Parser.NormalizeEpisodeTitle(episode.Title).Length,
return (title.Length > 0) && search.Contains(title); Episode = episode
}); })
.Where(e => e.Episode.Title.Length > 0 && e.Position >= 0)
.OrderBy(e => e.Position)
.ThenByDescending(e => e.Length)
.ToList();
return query.First().Episode;
} }
public List<Episode> EpisodesWithFiles(int seriesId) public List<Episode> EpisodesWithFiles(int seriesId)

Loading…
Cancel
Save