magefree / mage

Magic Another Game Engine
http://xmage.today
MIT License
1.86k stars 761 forks source link

Enhancement Request: Less Strict Searches #6548

Open Zerrisx opened 4 years ago

Zerrisx commented 4 years ago

Currently, if you search for:

"Jace the"

there will be no matches, even though it's fairly clear to a human that you would have liked to find:

"Jace, the Living Guild Pact" "Jace, the Mind Sculptor"

Can we make the search ignore missing punctuation when returning results?

As a bonus, it might also be nice if:

"Mindsculptor"

could find

"Jace, the Mind Sculptor"

i.e. be spacing ambivalent as well

etpalmer63 commented 4 years ago

Any chance you know where in the code the database queries are formed? I'm looking into this but its taking awhile to find the right place.

Zerrisx commented 4 years ago

Alas not; I'm not a developer and don't know the code well enough.

emerald000 commented 4 years ago

You're probably looking for CardSelector.filterCards().

etpalmer63 commented 4 years ago

Thanks for the help!@emerald000

After looking into it, it seams the search is returning all 40958 cards from the database before filtering gives the final results no matter what is typed into the search box. This can be seen by counting the difference in results from line 438 of CardSelector.java: java.util.List<CardInfo> foundCards = CardRepository.instance.findCards(buildCriteria()); and the number of filtered cards returned in filteredCards.

At this point, I'm still investigating. However, I guess that fuzzy matching will be much more difficult by filtering. There seems to be lots of documentation on how to do it constructively from the database querying approach. Also, performance of the search would likely increase if a more targeted query could be made.

My questions for the community:

  1. Is this correct? Is the whole database returned for each card search in the deck editor?
  2. If so, was there a reason for this decision?
JayDi85 commented 4 years ago

XMage uses autogenerated SQL queries to load cards from inner database. It's limited to search and filter (and limited to indexes too). That's why it uses runtime filter to search any data from card. So the main idea of current search logic: search cards for basic data by database and filter results with more accurate runtime code.

So you can modify CardTextPredicate to add lazy logic to search. As example:

  1. Prepare clean card text to lazy search (full name lowercase without spaces and other symbols, can add other replaces or extra info to "search string" like abbreviations, established hugs, or commands -- also it can contains original text for old searches). As example: card's cost can be store in "search index" by {R}{R}{G} and RRG at the same time. I think that's search data can be generated one time only on card load from database.
  2. Prepare clean search text (lowercase without spaces and other symbols). I also recommends to split spaces to multiple instances (e.g. "jace mind" goes to "text contains jace and text contains mind");
  3. Search.