home
products
contribute
download
documentation
forum
Home
Forums
New posts
Search forums
What's new
New posts
All posts
Latest activity
Members
Registered members
Current visitors
Donate
Log in
Register
What's new
Search
Search
Search titles only
By:
New posts
Search forums
Search titles only
By:
Menu
Log in
Register
Navigation
Install the app
Install
More options
Contact us
Close Menu
Forums
MediaPortal 1
Development
Improvement Suggestions
FuzzyMatch update suggestion
Contact us
RSS
JavaScript is disabled. For a better experience, please enable JavaScript in your browser before proceeding.
You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an
alternative browser
.
Reply to thread
Message
<blockquote data-quote="ChrL" data-source="post: 591173" data-attributes="member: 102882"><p>Since I'm not myself working on the project, I add my suggestion here. </p><p>My suggestion regards how to best match the actual movie. </p><p></p><p>I suggest that, in IMDBFetcher.cs, the FuzzyMatch is updated with the below.</p><p>Among other things it looks for the year in the title, since people often put it there, and looking for it helps disambiguating the movie.</p><p></p><p></p><p></p><p> public int FuzzyMatch(string name, string year)</p><p> { </p><p> List<int> matchingYearIndexes = new List<int>();</p><p> if (!string.IsNullOrEmpty(year))</p><p> {</p><p> for (int ixIx = 0; ixIx < _imdb.Count; ++ixIx) matchingYearIndexes.Add(ixIx);</p><p> FilterByYear(matchingYearIndexes, year);</p><p> if (matchingYearIndexes.Count == 1) return matchingYearIndexes[0]; </p><p> }</p><p> List<int> relevantIndexes = new List<int>();</p><p> if (matchingYearIndexes.Count > 1) foreach (int yearMatch in matchingYearIndexes) relevantIndexes.Add(yearMatch);</p><p> else for (int ixIx = 0; ixIx < _imdb.Count; ++ixIx) relevantIndexes.Add(ixIx);</p><p> </p><p> List<int> matchingIndexes = FilterByFuzz(name, relevantIndexes);</p><p> return matchingIndexes.Count > 0 ? matchingIndexes[0] : -1; </p><p> }</p><p></p><p> private List<int> FilterByFuzz(string name, List<int> relevantIndexes)</p><p> {</p><p> List<int> matchingIndexes = new List<int>();</p><p> int matchingDistance = int.MaxValue;</p><p> for (int ixIx = 0; ixIx < relevantIndexes.Count; ++ixIx)</p><p> {</p><p> int distance = Levenshtein.Match(name, _imdb[relevantIndexes[ixIx]].Title);</p><p></p><p> if (distance == matchingDistance && matchingDistance != int.MaxValue) matchingIndexes.Add(ixIx);</p><p> if (distance < matchingDistance)</p><p> {</p><p> matchingIndexes.Clear();</p><p> matchingIndexes.Add(ixIx);</p><p> matchingDistance = distance;</p><p> }</p><p> }</p><p> return matchingIndexes;</p><p> }</p><p></p><p> </p><p> private void FilterByYear(List<int> matchingIndexes, string year)</p><p> {</p><p> if (!string.IsNullOrEmpty(year))</p><p> {</p><p> for (int ixIx = matchingIndexes.Count - 1; ixIx > 0; ixIx--)</p><p> if (!_imdb[matchingIndexes[ixIx]].Title.Contains(year)) matchingIndexes.Remove(ixIx);</p><p> }</p><p> }</p><p></p><p></p><p></p><p></p><p></p><p> /// <summary></p><p> /// Download IMDB info for a movie</p><p> /// </summary></p><p> public static bool RefreshIMDB(IMDB.IProgress progress, ref IMDBMovie currentMovie, bool fuzzyMatching,</p><p> bool getActors, bool addToDatabase)</p><p> {</p><p> Log.Info("RefreshIMDB() - Refreshing MovieInfo for {0}-{1}", currentMovie.Title, currentMovie.SearchString);</p><p> string strMovieName = currentMovie.SearchString;</p><p> string strFileName = string.Empty;</p><p> string path = currentMovie.Path;</p><p> string filename = currentMovie.File;</p><p> if (path != string.Empty)</p><p> {</p><p> if (path.EndsWith(@"\"))</p><p> {</p><p> path = path.Substring(0, path.Length - 1);</p><p> currentMovie.Path = path;</p><p> }</p><p> if (filename.StartsWith(@"\"))</p><p> {</p><p> filename = filename.Substring(1);</p><p> currentMovie.File = filename;</p><p> }</p><p> strFileName = path + @"\" + filename;</p><p> }</p><p> else</p><p> {</p><p> strFileName = filename;</p><p> }</p><p> if ((strMovieName == string.Empty) || (strMovieName == Strings.Unknown))</p><p> {</p><p> strMovieName = currentMovie.Title;</p><p> if ((strMovieName == string.Empty) || (strMovieName == Strings.Unknown))</p><p> {</p><p> if (strFileName == string.Empty)</p><p> {</p><p> return true;</p><p> }</p><p> if (Util.Utils.IsDVD(strFileName))</p><p> {</p><p> //DVD</p><p> string strDrive = strFileName.Substring(0, 2);</p><p> currentMovie.DVDLabel = Util.Utils.GetDriveName(strDrive);</p><p> strMovieName = currentMovie.DVDLabel;</p><p> }</p><p> else if (strFileName.ToUpper().IndexOf(@"\VIDEO_TS\VIDEO_TS.IFO") >= 0)</p><p> {</p><p> //DVD folder</p><p> string dvdFolder = strFileName.Substring(0, strFileName.ToUpper().IndexOf(@"\VIDEO_TS\VIDEO_TS.IFO"));</p><p> currentMovie.DVDLabel = Path.GetFileName(dvdFolder);</p><p> strMovieName = currentMovie.DVDLabel;</p><p> }</p><p> else</p><p> {</p><p> //Movie </p><p> strMovieName = Path.GetFileNameWithoutExtension(strFileName);</p><p> }</p><p> }</p><p> if ((strMovieName == string.Empty) || (strMovieName == Strings.Unknown))</p><p> {</p><p> return true;</p><p> }</p><p> }</p><p> if (currentMovie.ID == -1 && addToDatabase)</p><p> {</p><p> currentMovie.ID = VideoDatabase.AddMovieFile(strFileName);</p><p> }</p><p> currentMovie.SearchString = strMovieName;</p><p> if (currentMovie.ID >= 0 || !addToDatabase)</p><p> {</p><p> if (!Win32API.IsConnectedToInternet())</p><p> {</p><p> return false;</p><p> }</p><p> IMDBFetcher fetcher = new IMDBFetcher(progress);</p><p> fetcher.Movie = currentMovie;</p><p> fetcher.getActors = getActors;</p><p> int selectedMovie = -1;</p><p></p><p> //LOOP</p><p> do</p><p> {</p><p> if (!fetcher.Fetch(strMovieName, !(selectedMovie < 0) ))</p><p> {</p><p> return false;</p><p> }</p><p></p><p> string year = string.Empty;</p><p> if (fetcher._imdb.Count == 0) </p><p> {</p><p> MatchChopper matchChopper = new MatchChopper(strMovieName);</p><p> while (fetcher._imdb.Count == 0 && matchChopper.MoveNext())</p><p> {</p><p> if (!fetcher.Fetch(matchChopper.Current, !(selectedMovie < 0) )) return false; </p><p> }</p><p> year = matchChopper.Year;</p><p> }</p><p></p><p> if (fuzzyMatching)</p><p> {</p><p> selectedMovie = fetcher.FuzzyMatch(fetcher.MovieName, year);</p><p> if (selectedMovie == -1)</p><p> {</p><p> if (!fetcher.OnMovieNotFound(fetcher)) return false; </p><p> if (!fetcher.OnRequestMovieTitle(fetcher, out strMovieName)) return false; </p><p> if (strMovieName == string.Empty) return false; </p><p> }</p><p> }</p><p> else</p><p> {</p><p> if (fetcher.Count > 0)</p><p> {</p><p> int iMoviesFound = fetcher.Count;</p><p> //GEMX 28.03.08: There should always be a choice to enter the movie manually </p><p> // in case the 1 and only found name is wrong</p><p> /*if (iMoviesFound == 1)</p><p> {</p><p> selectedMovie = 0;</p><p> } else */</p><p> if (iMoviesFound > 0)</p><p> {</p><p> if (!fetcher.OnSelectMovie(fetcher, out selectedMovie))</p><p> {</p><p> return false;</p><p> }</p><p> if (selectedMovie < 0)</p><p> {</p><p> if (!fetcher.OnRequestMovieTitle(fetcher, out strMovieName))</p><p> { </p><p> return false; </p><p> }</p><p> if (strMovieName == string.Empty)</p><p> {</p><p> return false;</p><p> }</p><p> }</p><p> }</p><p> }</p><p> else</p><p> {</p><p> if (!fetcher.OnMovieNotFound(fetcher)) </p><p> { </p><p> return false; </p><p> }</p><p> if (!fetcher.OnRequestMovieTitle(fetcher, out strMovieName))</p><p> {</p><p> return false;</p><p> }</p><p> if (strMovieName == string.Empty)</p><p> {</p><p> return false;</p><p> }</p><p> }</p><p> }</p><p> } while (selectedMovie < 0);</p><p> </p><p></p><p> if (!fetcher.FetchDetails(selectedMovie, ref currentMovie))</p><p> {</p><p> return false;</p><p> }</p><p> IMDBMovie movieDetails = fetcher.Movie;</p><p></p><p> if (movieDetails != null)</p><p> {</p><p> movieDetails.SearchString = strMovieName;</p><p> currentMovie = movieDetails;</p><p> return true;</p><p> }</p><p> else</p><p> {</p><p> return fetcher.OnDetailsNotFound(fetcher);</p><p> }</p><p> }</p><p> return false;</p><p> }</p><p> </p><p> public class MatchChopper : IEnumerator<string></p><p> {</p><p> string orgName;</p><p> string movieName;</p><p> string rest;</p><p> public string Year;</p><p> bool useRest = false;</p><p></p><p> public MatchChopper(string movieName)</p><p> {</p><p> this.orgName = movieName;</p><p> this.movieName = movieName;</p><p> this.rest = string.Empty;</p><p> }</p><p></p><p> public string Current { get { return movieName; } }</p><p> object IEnumerator.Current { get { return movieName; } }</p><p> public void Reset() { movieName = orgName; rest = string.Empty; useRest = false; }</p><p> public void Dispose() { }</p><p></p><p> public bool MoveNext()</p><p> {</p><p> string[] looseSplit = movieName.Split(new char[] { ' ', ',', '.', '(', ')', '[', ']' }, StringSplitOptions.RemoveEmptyEntries);</p><p> int findIx = Array.FindIndex<string>(looseSplit, IsYearOfMovie);</p><p> if (findIx > 0)</p><p> {</p><p> Year = looseSplit[findIx];</p><p> looseSplit[findIx] = string.Empty;</p><p> movieName = Combine(looseSplit, " ");</p><p> return true;</p><p> }</p><p> else</p><p> {</p><p> //if (!string.IsNullOrEmpty(rest)) movieName = rest;</p><p> if (useRest) movieName = rest; </p><p> string[] dashSplit = movieName.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries); </p><p> if (dashSplit.Length>0)</p><p> {</p><p> movieName = dashSplit[0];</p><p> string upperTrimmed = movieName.ToUpper().Trim();</p><p> if (dashSplit.Length>1) </p><p> if (unimplemented_UserDefinedListOfWordsToIgnore.IndexOf(upperTrimmed)>-1))</p><p> {</p><p> movieName = dashSplit[1];</p><p> dashSplit[1] = string.Empty;</p><p> }</p><p> dashSplit[0] = string.Empty;</p><p> rest = Combine(dashSplit, " ");</p><p> useRest = true; </p><p> return true;</p><p> }</p><p> else</p><p> {</p><p> return false;</p><p> } </p><p> } </p><p> }</p><p></p><p> bool IsYearOfMovie(string text)</p><p> {</p><p> int year;</p><p> if (text.Length==6)</p><p> if ((text[0] == '{' || text[0] == '(' || text[0] == '[') &&</p><p> (text[0] == '}' || text[0] == ')' || text[0] == ']'))</p><p> {</p><p> text = text.Substring(1,4);</p><p> }</p><p> return (int.TryParse(text, out year) && (year > 1800) && (year <= DateTime.Now.Year + 3));</p><p> }</p><p></p><p> string Combine(string[] split, string delimiter)</p><p> {</p><p> StringBuilder sb = new StringBuilder();</p><p> bool first = true;</p><p> foreach (string s in split)</p><p> {</p><p> if (first == false) sb.Append(delimiter);</p><p> sb.Append(s);</p><p> first = false;</p><p> }</p><p> return sb.ToString();</p><p> }</p><p> }</p></blockquote><p></p>
[QUOTE="ChrL, post: 591173, member: 102882"] Since I'm not myself working on the project, I add my suggestion here. My suggestion regards how to best match the actual movie. I suggest that, in IMDBFetcher.cs, the FuzzyMatch is updated with the below. Among other things it looks for the year in the title, since people often put it there, and looking for it helps disambiguating the movie. public int FuzzyMatch(string name, string year) { List<int> matchingYearIndexes = new List<int>(); if (!string.IsNullOrEmpty(year)) { for (int ixIx = 0; ixIx < _imdb.Count; ++ixIx) matchingYearIndexes.Add(ixIx); FilterByYear(matchingYearIndexes, year); if (matchingYearIndexes.Count == 1) return matchingYearIndexes[0]; } List<int> relevantIndexes = new List<int>(); if (matchingYearIndexes.Count > 1) foreach (int yearMatch in matchingYearIndexes) relevantIndexes.Add(yearMatch); else for (int ixIx = 0; ixIx < _imdb.Count; ++ixIx) relevantIndexes.Add(ixIx); List<int> matchingIndexes = FilterByFuzz(name, relevantIndexes); return matchingIndexes.Count > 0 ? matchingIndexes[0] : -1; } private List<int> FilterByFuzz(string name, List<int> relevantIndexes) { List<int> matchingIndexes = new List<int>(); int matchingDistance = int.MaxValue; for (int ixIx = 0; ixIx < relevantIndexes.Count; ++ixIx) { int distance = Levenshtein.Match(name, _imdb[relevantIndexes[ixIx]].Title); if (distance == matchingDistance && matchingDistance != int.MaxValue) matchingIndexes.Add(ixIx); if (distance < matchingDistance) { matchingIndexes.Clear(); matchingIndexes.Add(ixIx); matchingDistance = distance; } } return matchingIndexes; } private void FilterByYear(List<int> matchingIndexes, string year) { if (!string.IsNullOrEmpty(year)) { for (int ixIx = matchingIndexes.Count - 1; ixIx > 0; ixIx--) if (!_imdb[matchingIndexes[ixIx]].Title.Contains(year)) matchingIndexes.Remove(ixIx); } } /// <summary> /// Download IMDB info for a movie /// </summary> public static bool RefreshIMDB(IMDB.IProgress progress, ref IMDBMovie currentMovie, bool fuzzyMatching, bool getActors, bool addToDatabase) { Log.Info("RefreshIMDB() - Refreshing MovieInfo for {0}-{1}", currentMovie.Title, currentMovie.SearchString); string strMovieName = currentMovie.SearchString; string strFileName = string.Empty; string path = currentMovie.Path; string filename = currentMovie.File; if (path != string.Empty) { if (path.EndsWith(@"\")) { path = path.Substring(0, path.Length - 1); currentMovie.Path = path; } if (filename.StartsWith(@"\")) { filename = filename.Substring(1); currentMovie.File = filename; } strFileName = path + @"\" + filename; } else { strFileName = filename; } if ((strMovieName == string.Empty) || (strMovieName == Strings.Unknown)) { strMovieName = currentMovie.Title; if ((strMovieName == string.Empty) || (strMovieName == Strings.Unknown)) { if (strFileName == string.Empty) { return true; } if (Util.Utils.IsDVD(strFileName)) { //DVD string strDrive = strFileName.Substring(0, 2); currentMovie.DVDLabel = Util.Utils.GetDriveName(strDrive); strMovieName = currentMovie.DVDLabel; } else if (strFileName.ToUpper().IndexOf(@"\VIDEO_TS\VIDEO_TS.IFO") >= 0) { //DVD folder string dvdFolder = strFileName.Substring(0, strFileName.ToUpper().IndexOf(@"\VIDEO_TS\VIDEO_TS.IFO")); currentMovie.DVDLabel = Path.GetFileName(dvdFolder); strMovieName = currentMovie.DVDLabel; } else { //Movie strMovieName = Path.GetFileNameWithoutExtension(strFileName); } } if ((strMovieName == string.Empty) || (strMovieName == Strings.Unknown)) { return true; } } if (currentMovie.ID == -1 && addToDatabase) { currentMovie.ID = VideoDatabase.AddMovieFile(strFileName); } currentMovie.SearchString = strMovieName; if (currentMovie.ID >= 0 || !addToDatabase) { if (!Win32API.IsConnectedToInternet()) { return false; } IMDBFetcher fetcher = new IMDBFetcher(progress); fetcher.Movie = currentMovie; fetcher.getActors = getActors; int selectedMovie = -1; //LOOP do { if (!fetcher.Fetch(strMovieName, !(selectedMovie < 0) )) { return false; } string year = string.Empty; if (fetcher._imdb.Count == 0) { MatchChopper matchChopper = new MatchChopper(strMovieName); while (fetcher._imdb.Count == 0 && matchChopper.MoveNext()) { if (!fetcher.Fetch(matchChopper.Current, !(selectedMovie < 0) )) return false; } year = matchChopper.Year; } if (fuzzyMatching) { selectedMovie = fetcher.FuzzyMatch(fetcher.MovieName, year); if (selectedMovie == -1) { if (!fetcher.OnMovieNotFound(fetcher)) return false; if (!fetcher.OnRequestMovieTitle(fetcher, out strMovieName)) return false; if (strMovieName == string.Empty) return false; } } else { if (fetcher.Count > 0) { int iMoviesFound = fetcher.Count; //GEMX 28.03.08: There should always be a choice to enter the movie manually // in case the 1 and only found name is wrong /*if (iMoviesFound == 1) { selectedMovie = 0; } else */ if (iMoviesFound > 0) { if (!fetcher.OnSelectMovie(fetcher, out selectedMovie)) { return false; } if (selectedMovie < 0) { if (!fetcher.OnRequestMovieTitle(fetcher, out strMovieName)) { return false; } if (strMovieName == string.Empty) { return false; } } } } else { if (!fetcher.OnMovieNotFound(fetcher)) { return false; } if (!fetcher.OnRequestMovieTitle(fetcher, out strMovieName)) { return false; } if (strMovieName == string.Empty) { return false; } } } } while (selectedMovie < 0); if (!fetcher.FetchDetails(selectedMovie, ref currentMovie)) { return false; } IMDBMovie movieDetails = fetcher.Movie; if (movieDetails != null) { movieDetails.SearchString = strMovieName; currentMovie = movieDetails; return true; } else { return fetcher.OnDetailsNotFound(fetcher); } } return false; } public class MatchChopper : IEnumerator<string> { string orgName; string movieName; string rest; public string Year; bool useRest = false; public MatchChopper(string movieName) { this.orgName = movieName; this.movieName = movieName; this.rest = string.Empty; } public string Current { get { return movieName; } } object IEnumerator.Current { get { return movieName; } } public void Reset() { movieName = orgName; rest = string.Empty; useRest = false; } public void Dispose() { } public bool MoveNext() { string[] looseSplit = movieName.Split(new char[] { ' ', ',', '.', '(', ')', '[', ']' }, StringSplitOptions.RemoveEmptyEntries); int findIx = Array.FindIndex<string>(looseSplit, IsYearOfMovie); if (findIx > 0) { Year = looseSplit[findIx]; looseSplit[findIx] = string.Empty; movieName = Combine(looseSplit, " "); return true; } else { //if (!string.IsNullOrEmpty(rest)) movieName = rest; if (useRest) movieName = rest; string[] dashSplit = movieName.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries); if (dashSplit.Length>0) { movieName = dashSplit[0]; string upperTrimmed = movieName.ToUpper().Trim(); if (dashSplit.Length>1) if (unimplemented_UserDefinedListOfWordsToIgnore.IndexOf(upperTrimmed)>-1)) { movieName = dashSplit[1]; dashSplit[1] = string.Empty; } dashSplit[0] = string.Empty; rest = Combine(dashSplit, " "); useRest = true; return true; } else { return false; } } } bool IsYearOfMovie(string text) { int year; if (text.Length==6) if ((text[0] == '{' || text[0] == '(' || text[0] == '[') && (text[0] == '}' || text[0] == ')' || text[0] == ']')) { text = text.Substring(1,4); } return (int.TryParse(text, out year) && (year > 1800) && (year <= DateTime.Now.Year + 3)); } string Combine(string[] split, string delimiter) { StringBuilder sb = new StringBuilder(); bool first = true; foreach (string s in split) { if (first == false) sb.Append(delimiter); sb.Append(s); first = false; } return sb.ToString(); } } [/QUOTE]
Insert quotes…
Verification
Post reply
Forums
MediaPortal 1
Development
Improvement Suggestions
FuzzyMatch update suggestion
Contact us
RSS
Top
Bottom