Fix multi-word type matching in card filters (#6060)

* Fix multi-word type matching in card filters

Add phrase matching to StringValue before word-based fallback.
Enables searches like t:"time lord" for multi-word creature types.

* Use existing typedef

* Don't inline lambda

* update filter func

* Update card type FilterString unit tests

* refactor string matcher

* update card db test

* fix sets count in test

* Add regex cache in string matcher

* Update cockatrice/src/game/filters/filter_string.cpp

* Revert "Add regex cache in string matcher"

---------

Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com>
This commit is contained in:
Paul Carroll 2025-08-24 12:37:25 -04:00 committed by GitHub
parent ba794c2b60
commit 5e88a0f0cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 36 additions and 6 deletions

View file

@ -187,15 +187,25 @@ static void setupParserRules()
return QString::fromStdString(std::string(sv.sv())).toLower();
};
search["StringValue"] = [](const peg::SemanticValues &sv) -> StringMatcher {
// Helper function for word boundary matching
auto createWordBoundaryMatcher = [](const QString &target) {
QString pattern = QString("\\b%1\\b").arg(QRegularExpression::escape(target));
QRegularExpression regex(pattern, QRegularExpression::CaseInsensitiveOption);
return [regex](const QString &s) { return regex.match(s).hasMatch(); };
};
if (sv.choice() == 0) {
const auto target = std::any_cast<QString>(sv[0]);
return [=](const QString &s) { return s.split(" ").contains(target, Qt::CaseInsensitive); };
return createWordBoundaryMatcher(target);
}
const auto target = std::any_cast<QStringList>(sv[0]);
return [=](const QString &s) {
auto containsString = [&s](const QString &str) { return s.split(" ").contains(str, Qt::CaseInsensitive); };
auto containsString = [&s, &createWordBoundaryMatcher](const QString &str) {
return createWordBoundaryMatcher(str)(s);
};
return std::any_of(target.begin(), target.end(), containsString);
};
};