public async Task <TranslatedSearchResult <ICard> > FindCard(SearchParameters parameters) { string sTerm = parameters.SearchTerm; Locale sLoc = parameters.SearchLocale; Locale? tLoc = parameters.TranslationLocale; Version ver = parameters.Version; Catalog sCat = await CatalogService.GetCatalog(sLoc, ver); Catalog?tCat = tLoc is null ? null : await CatalogService.GetCatalog(tLoc, ver); if (TryFindCardFromCode(sTerm, tCat ?? sCat, out TranslatedSearchResult <ICard>?codeResult)) { return(codeResult !); } var cardSearcher = new CatalogItemSearcher <ICard> ( sCat, new CardNameGrouper() ) { TermTargetCanonicalizer = new TrimmedAndLowerCanonicalizer(), TermMatcherFactory = new LevenshteinSubstringMatcher.Factory(GreengladeSettings.SubstringBookendWeight, GreengladeSettings.SubstringBookendTaper), KeyStrengthThreshold = GreengladeSettings.StringMatchThreshold, KeyConflictResolution = KeyConflictResolution.Flattened, MatchGroupResolver = new BasicCardGroupResolver(), ItemStrengthDownscalers = new[] { new UncollectibleCardStrengthDownscaler(GreengladeSettings.UncollectibleCardDownscaleFactor) }, ItemDownscaleCurve = ItemDownscaleCurve.Biased, ItemMatchSorter = new DescendingMatchStrengthSorter <ICard>(), }; SearchResult <ICard> result = cardSearcher.Search(sTerm); if (tCat is null) { return(TranslatedSearchResult <ICard> .FromUntranslatedSearch(result)); } var tMap = new Dictionary <ICard, ICard>(); foreach (var match in result.Matches) { ICard sItem = match.Item; if (tCat.Cards.TryGetValue(sItem.Code, out var tItem)) { tMap.Add(sItem, tItem); } else { LogCouldNotTranslateWarning(sItem, sLoc, tCat.Locale, ver); } } return(TranslatedSearchResult <ICard> .FromTranslatedSearch(result, tCat.Locale, tMap)); }
public async Task <TranslatedSearchResult <CatalogItemUnion> > FindAnything(SearchParameters parameters) { return(TranslatedSearchResult <CatalogItemUnion> .MergeSearchResults ( await FindCard(parameters), await FindKeyword(parameters), await FindDeck(parameters), new DescendingMatchStrengthSorter <CatalogItemUnion>() )); }
public async Task <TranslatedSearchResult <LorKeyword> > FindKeyword(SearchParameters parameters) { string sTerm = parameters.SearchTerm; Locale sLoc = parameters.SearchLocale; Locale? tLoc = parameters.TranslationLocale; Version ver = parameters.Version; Catalog sCat = await CatalogService.GetCatalog(sLoc, ver); Catalog?tCat = tLoc is null ? null : await CatalogService.GetCatalog(tLoc, ver); var keywordSearcher = new CatalogItemSearcher <LorKeyword> ( sCat, new KeywordNameGrouper { IncludeVocabTerms = true, IncludeDescriptionlessKeywords = false } ) { TermTargetCanonicalizer = new TrimmedAndLowerCanonicalizer(), TermMatcherFactory = new LevenshteinSubstringMatcher.Factory(GreengladeSettings.SubstringBookendWeight, GreengladeSettings.SubstringBookendTaper), KeyStrengthThreshold = GreengladeSettings.StringMatchThreshold, ItemMatchSorter = new DescendingMatchStrengthSorter <LorKeyword>(), }; SearchResult <LorKeyword> result = keywordSearcher.Search(sTerm); if (tCat is null) { return(TranslatedSearchResult <LorKeyword> .FromUntranslatedSearch(result)); } var tMap = new Dictionary <LorKeyword, LorKeyword>(); foreach (var match in result.Matches) { LorKeyword sItem = match.Item; if (tCat.Keywords.TryGetValue(sItem.Key, out var tItem)) { tMap.Add(sItem, tItem); } else if (tCat.VocabTerms.TryGetValue(sItem.Key, out var vtItem)) { tItem = new LorKeyword(sItem.Key, vtItem.Name, vtItem.Description); tMap.Add(sItem, tItem); } else { LogCouldNotTranslateWarning(sItem, sLoc, tCat.Locale, ver); } } return(TranslatedSearchResult <LorKeyword> .FromTranslatedSearch(result, tCat.Locale, tMap)); }
private static bool TryFindDeckFromCode(string term, Catalog catalog, out TranslatedSearchResult <Deck>?result) { if (Deck.TryFromCode(term, catalog, out Deck? deck)) { var usr = SearchResult <Deck> .FromSingleItem(term, catalog.Locale, catalog.Version, deck !); result = TranslatedSearchResult <Deck> .FromUntranslatedSearch(usr); return(true); } else { result = null; return(false); } }
private static bool TryFindCardFromCode(string term, Catalog catalog, out TranslatedSearchResult <ICard>?result) { if (catalog.Cards.TryGetValue(term, out ICard? card)) { var usr = SearchResult <ICard> .FromSingleItem(term, catalog.Locale, catalog.Version, card); result = TranslatedSearchResult <ICard> .FromUntranslatedSearch(usr); return(true); } else { result = null; return(false); } }
public async Task <TranslatedSearchResult <Deck> > FindDeck(SearchParameters parameters) { string term = parameters.SearchTerm; Locale loc = parameters.TranslationLocale ?? parameters.SearchLocale; Version ver = parameters.Version; Catalog cat = await CatalogService.GetCatalog(loc, ver); if (TryFindDeckFromCode(term, cat, out TranslatedSearchResult <Deck>?result)) { return(result !); } else { return(TranslatedSearchResult <Deck> .FromUntranslatedSearch(new SearchResult <Deck>(term, loc, ver))); } }
public async Task <MessageView> BuildView(TranslatedSearchResult <T> item) { IReadOnlyList <ItemMatch <T> > matches = item.Matches; if (matches.Count == 0) { return(new MessageView($"No results found.")); } string?didYouMean = null; if (matches.Count > 1) { IEnumerable <string?> names = matches.Skip(1).Select(m => $"**{GetItemName(m.Item)}**"); string namesOutput = string.Join(" | ", names); didYouMean = $"Did you mean: {namesOutput}"; if (didYouMean.Length > 2048) { string s = matches.Count == 2 ? "" : "s"; didYouMean = $"*{matches.Count - 1} other result{s}*"; } } T uItem = matches[0].Item; item.TranslationMap.TryGetValue(uItem, out T? tItem); IEnumerable <T> expansion = await ExpandItem(tItem ?? uItem); MessageView[] views = await Task.WhenAll(expansion.Select(BuildItemView)); var messages = new List <MessageInfo>(); if (didYouMean is null) { // Just render all item views foreach (MessageView view in views) { messages.AddRange(view.Messages); } } else if (views.Length == 1 && views[0].Messages.Count == 1) { // Send the text reply in the same message as the single item message if possible MessageInfo itemMessage = views[0].Messages[0]; if (itemMessage.Text is null) { messages.Add(new MessageInfo { Text = didYouMean, Embed = itemMessage.Embed }); } else { messages.Add(didYouMean); messages.Add(itemMessage); } } else { // Send the text reply separately from the multiple item messages messages.Add(didYouMean); foreach (MessageView view in views) { messages.AddRange(view.Messages); } } return(new MessageView(messages)); }