Exemplo n.º 1
0
        /// <summary>
        ///     function used in fuzzy search
        /// </summary>
        /// <param name="grouping"></param>
        /// <param name="query"></param>
        private static SearchGrouping CheckTitlesFuzzy(IGrouping <int, SVR_AnimeSeries> grouping, string query)
        {
            if (!(grouping?.SelectMany(a => a.GetAllTitles()).Any() ?? false))
            {
                return(null);
            }
            SearchGrouping dist = null;

            foreach (SVR_AnimeSeries item in grouping)
            {
                foreach (string title in item.GetAllTitles())
                {
                    if (string.IsNullOrEmpty(title))
                    {
                        continue;
                    }
                    int k = Math.Max(Math.Min((int)(title.Length / 6D), (int)(query.Length / 6D)), 1);
                    if (query.Length <= 4 || title.Length <= 4)
                    {
                        k = 0;
                    }

                    Misc.SearchInfo <IGrouping <int, SVR_AnimeSeries> > result =
                        Misc.DiceFuzzySearch(title, query, k, grouping);
                    if (result.Index == -1)
                    {
                        continue;
                    }
                    SearchGrouping searchGrouping = new SearchGrouping
                    {
                        Distance   = result.Distance,
                        Index      = result.Index,
                        ExactMatch = result.ExactMatch,
                        Match      = title,
                        Results    = grouping.OrderBy(a => a.AirDate).ToList()
                    };
                    if (result.Distance < (dist?.Distance ?? int.MaxValue))
                    {
                        dist = searchGrouping;
                    }
                }
            }

            return(dist);
        }
Exemplo n.º 2
0
        /// <summary>
        ///     function used in fuzzy search
        /// </summary>
        /// <param name="grouping"></param>
        /// <param name="query"></param>
        private static SearchGrouping CheckTitlesIndexOf(IGrouping <int, SVR_AnimeSeries> grouping, string query)
        {
            if (!(grouping?.SelectMany(a => a.GetAllTitles()).Any() ?? false))
            {
                return(null);
            }
            SearchGrouping dist = null;

            foreach (SVR_AnimeSeries item in grouping)
            {
                foreach (string title in item.GetAllTitles())
                {
                    if (string.IsNullOrEmpty(title))
                    {
                        continue;
                    }
                    int result = title.IndexOf(query, StringComparison.OrdinalIgnoreCase);
                    if (result == -1)
                    {
                        continue;
                    }
                    SearchGrouping searchGrouping = new SearchGrouping
                    {
                        Distance   = 0,
                        Index      = result,
                        ExactMatch = true,
                        Match      = title,
                        Results    = grouping.OrderBy(a => a.AirDate).ToList()
                    };
                    if (result < (dist?.Index ?? int.MaxValue))
                    {
                        dist = searchGrouping;
                    }
                }
            }

            return(dist);
        }
Exemplo n.º 3
0
        public ActionResult <IEnumerable <SeriesSearchResult> > Search(string query, int limit = int.MaxValue)
        {
            SorensenDice search = new SorensenDice();

            query = query.ToLowerInvariant();
            query = query.Replace("+", " ");

            List <SeriesSearchResult>       seriesList = new List <SeriesSearchResult>();
            ParallelQuery <SVR_AnimeSeries> allSeries  = RepoFactory.AnimeSeries.GetAll()
                                                         .Where(a => a?.Contract?.AniDBAnime?.AniDBAnime != null &&
                                                                !a.Contract.AniDBAnime.Tags.Select(b => b.TagName)
                                                                .FindInEnumerable(User.GetHideCategories()))
                                                         .AsParallel();

            HashSet <string> languages = new HashSet <string> {
                "en", "x-jat"
            };

            languages.UnionWith(ServerSettings.Instance.LanguagePreference);
            var distLevenshtein = new ConcurrentDictionary <SVR_AnimeSeries, Tuple <double, string> >();

            allSeries.ForAll(a => CheckTitlesFuzzy(search, languages, a, query, ref distLevenshtein, limit));

            var tempListToSort = distLevenshtein.Keys.GroupBy(a => a.AnimeGroupID).Select(a =>
            {
                var tempSeries = a.ToList();
                tempSeries.Sort((j, k) =>
                {
                    var result1    = distLevenshtein[j];
                    var result2    = distLevenshtein[k];
                    var exactMatch = result1.Item1.CompareTo(result2.Item1);
                    if (exactMatch != 0)
                    {
                        return(exactMatch);
                    }

                    string title1 = j.GetSeriesName();
                    string title2 = k.GetSeriesName();
                    if (title1 == null && title2 == null)
                    {
                        return(0);
                    }
                    if (title1 == null)
                    {
                        return(1);
                    }
                    if (title2 == null)
                    {
                        return(-1);
                    }
                    return(string.Compare(title1, title2, StringComparison.InvariantCultureIgnoreCase));
                });
                var result = new SearchGrouping
                {
                    Series   = a.OrderBy(b => b.AirDate).ToList(),
                    Distance = distLevenshtein[tempSeries[0]].Item1,
                    Match    = distLevenshtein[tempSeries[0]].Item2
                };
                return(result);
            });

            Dictionary <SVR_AnimeSeries, Tuple <double, string> > series = tempListToSort.OrderBy(a => a.Distance)
                                                                           .ThenBy(a => a.Match.Length).SelectMany(a => a.Series).ToDictionary(a => a, a => distLevenshtein[a]);

            foreach (KeyValuePair <SVR_AnimeSeries, Tuple <double, string> > ser in series)
            {
                seriesList.Add(new SeriesSearchResult(HttpContext, ser.Key, ser.Value.Item2, ser.Value.Item1));
                if (seriesList.Count >= limit)
                {
                    break;
                }
            }

            return(seriesList);
        }