From 97c9217c0d647684e09a58be2ff1ef1cd52de133 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 5 Nov 2014 08:45:50 -0800 Subject: [PATCH] Fixed: Improved title sorting for 'A to Z' --- .../MetadataSourceTests/TraktProxyFixture.cs | 2 +- .../NzbDrone.Core.Test.csproj | 1 + .../TvTests/SeriesTitleNormalizerFixture.cs | 28 +++++++++++++++++++ .../Migration/053_add_series_sorttitle.cs | 2 +- .../MetadataSource/TraktProxy.cs | 2 +- src/NzbDrone.Core/NzbDrone.Core.csproj | 1 + src/NzbDrone.Core/Parser/Parser.cs | 2 +- src/NzbDrone.Core/Tv/EpisodeService.cs | 4 +-- src/NzbDrone.Core/Tv/SeriesService.cs | 2 +- src/NzbDrone.Core/Tv/SeriesTitleNormalizer.cs | 23 +++++++++++++++ 10 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/NzbDrone.Core.Test/TvTests/SeriesTitleNormalizerFixture.cs create mode 100644 src/NzbDrone.Core/Tv/SeriesTitleNormalizer.cs diff --git a/src/NzbDrone.Core.Test/MetadataSourceTests/TraktProxyFixture.cs b/src/NzbDrone.Core.Test/MetadataSourceTests/TraktProxyFixture.cs index d1bec7016..30d932ef9 100644 --- a/src/NzbDrone.Core.Test/MetadataSourceTests/TraktProxyFixture.cs +++ b/src/NzbDrone.Core.Test/MetadataSourceTests/TraktProxyFixture.cs @@ -85,7 +85,7 @@ namespace NzbDrone.Core.Test.MetadataSourceTests series.Should().NotBeNull(); series.Title.Should().NotBeNullOrWhiteSpace(); series.CleanTitle.Should().Be(Parser.Parser.CleanSeriesTitle(series.Title)); - series.SortTitle.Should().Be(Parser.Parser.NormalizeEpisodeTitle(series.Title)); + series.SortTitle.Should().Be(SeriesTitleNormalizer.Normalize(series.Title, series.TvdbId)); series.Overview.Should().NotBeNullOrWhiteSpace(); series.AirTime.Should().NotBeNullOrWhiteSpace(); series.FirstAired.Should().HaveValue(); diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 32bbf520f..5d8c1ffa6 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -292,6 +292,7 @@ + diff --git a/src/NzbDrone.Core.Test/TvTests/SeriesTitleNormalizerFixture.cs b/src/NzbDrone.Core.Test/TvTests/SeriesTitleNormalizerFixture.cs new file mode 100644 index 000000000..ddc8bb879 --- /dev/null +++ b/src/NzbDrone.Core.Test/TvTests/SeriesTitleNormalizerFixture.cs @@ -0,0 +1,28 @@ +using System; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Test.TvTests +{ + [TestFixture] + public class SeriesTitleNormalizerFixture + { + [Test] + public void should_use_precomputed_title_for_a_to_z() + { + SeriesTitleNormalizer.Normalize("A to Z", 281588).Should().Be("a to z"); + } + + [TestCase("2 Broke Girls", "2 broke girls")] + [TestCase("Archer (2009)", "archer 2009")] + [TestCase("The Office (US)", "office us")] + [TestCase("The Mentalist", "mentalist")] + [TestCase("The Good Wife", "good wife")] + [TestCase("The Newsroom (2012)", "newsroom 2012")] + public void should_normalize_title(String title, String expected) + { + SeriesTitleNormalizer.Normalize(title, 0).Should().Be(expected); + } + } +} diff --git a/src/NzbDrone.Core/Datastore/Migration/053_add_series_sorttitle.cs b/src/NzbDrone.Core/Datastore/Migration/053_add_series_sorttitle.cs index fccaa97b1..46e1b8ce3 100644 --- a/src/NzbDrone.Core/Datastore/Migration/053_add_series_sorttitle.cs +++ b/src/NzbDrone.Core/Datastore/Migration/053_add_series_sorttitle.cs @@ -27,7 +27,7 @@ namespace NzbDrone.Core.Datastore.Migration var id = seriesReader.GetInt32(0); var title = seriesReader.GetString(1); - var sortTitle = Parser.Parser.NormalizeEpisodeTitle(title).ToLower(); + var sortTitle = Parser.Parser.NormalizeTitle(title).ToLower(); using (IDbCommand updateCmd = conn.CreateCommand()) { diff --git a/src/NzbDrone.Core/MetadataSource/TraktProxy.cs b/src/NzbDrone.Core/MetadataSource/TraktProxy.cs index 9ffc02b6a..c80640427 100644 --- a/src/NzbDrone.Core/MetadataSource/TraktProxy.cs +++ b/src/NzbDrone.Core/MetadataSource/TraktProxy.cs @@ -134,7 +134,7 @@ namespace NzbDrone.Core.MetadataSource series.ImdbId = show.imdb_id; series.Title = show.title; series.CleanTitle = Parser.Parser.CleanSeriesTitle(show.title); - series.SortTitle = Parser.Parser.NormalizeEpisodeTitle(show.title).ToLower(); + series.SortTitle = SeriesTitleNormalizer.Normalize(show.title, show.tvdb_id); series.Year = GetYear(show.year, show.first_aired); series.FirstAired = FromIso(show.first_aired_iso); series.Overview = show.overview; diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 4d7374cbf..74ad39c70 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -765,6 +765,7 @@ Code + diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 743171d92..400d4f9fb 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -323,7 +323,7 @@ namespace NzbDrone.Core.Parser return MultiPartCleanupRegex.Replace(title, string.Empty).Trim(); } - public static string NormalizeEpisodeTitle(string title) + public static string NormalizeTitle(string title) { string singleSpaces = WordDelimiterRegex.Replace(title, " "); string noPunctuation = PunctuationRegex.Replace(singleSpaces, String.Empty); diff --git a/src/NzbDrone.Core/Tv/EpisodeService.cs b/src/NzbDrone.Core/Tv/EpisodeService.cs index a9a08cf00..a968fff9b 100644 --- a/src/NzbDrone.Core/Tv/EpisodeService.cs +++ b/src/NzbDrone.Core/Tv/EpisodeService.cs @@ -106,12 +106,12 @@ namespace NzbDrone.Core.Tv public Episode FindEpisodeByName(int seriesId, int seasonNumber, string episodeTitle) { // TODO: can replace this search mechanism with something smarter/faster/better - var search = Parser.Parser.NormalizeEpisodeTitle(episodeTitle); + var search = Parser.Parser.NormalizeTitle(episodeTitle); return _episodeRepository.GetEpisodes(seriesId, seasonNumber) .FirstOrDefault(e => { // normalize episode title - string title = Parser.Parser.NormalizeEpisodeTitle(e.Title); + string title = Parser.Parser.NormalizeTitle(e.Title); // find episode title within search string return (title.Length > 0) && search.Contains(title); }); diff --git a/src/NzbDrone.Core/Tv/SeriesService.cs b/src/NzbDrone.Core/Tv/SeriesService.cs index b444ff63f..58586d6cb 100644 --- a/src/NzbDrone.Core/Tv/SeriesService.cs +++ b/src/NzbDrone.Core/Tv/SeriesService.cs @@ -77,7 +77,7 @@ namespace NzbDrone.Core.Tv newSeries.Monitored = true; newSeries.CleanTitle = newSeries.Title.CleanSeriesTitle(); - newSeries.SortTitle = Parser.Parser.NormalizeEpisodeTitle(newSeries.Title).ToLower(); + newSeries.SortTitle = SeriesTitleNormalizer.Normalize(newSeries.Title, newSeries.TvdbId); _seriesRepository.Insert(newSeries); _eventAggregator.PublishEvent(new SeriesAddedEvent(GetSeries(newSeries.Id))); diff --git a/src/NzbDrone.Core/Tv/SeriesTitleNormalizer.cs b/src/NzbDrone.Core/Tv/SeriesTitleNormalizer.cs new file mode 100644 index 000000000..532d60ea6 --- /dev/null +++ b/src/NzbDrone.Core/Tv/SeriesTitleNormalizer.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; + +namespace NzbDrone.Core.Tv +{ + public static class SeriesTitleNormalizer + { + private readonly static Dictionary PreComputedTitles = new Dictionary + { + { 281588, "a to z" } + }; + + public static String Normalize(String title, Int32 tvdbId) + { + if (PreComputedTitles.ContainsKey(tvdbId)) + { + return PreComputedTitles[tvdbId]; + } + + return Parser.Parser.NormalizeTitle(title).ToLower(); + } + } +}