mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-21 00:55:09 -07:00
Allow to filter sets by release date (#7239)
This compares the release dates of sets, which enables users to filter for sets in a certain range, for example to filter for all commanders with an old card frame, `t:legendary set<8ED` can be used, which will only include cards appearing before 8th edition. This acts as a more powerful superset of the "Filter to X most recent sets" feature. Fixes #7238
This commit is contained in:
parent
c011ea7ceb
commit
0c725f9a03
3 changed files with 51 additions and 19 deletions
|
|
@ -52,6 +52,7 @@ In this list of examples below, each entry has an explanation and can be clicked
|
||||||
<dt><u>E</u>dition:</dt>
|
<dt><u>E</u>dition:</dt>
|
||||||
<dd>[set:lea](#set:lea) <small>(Cards that appear in Alpha, which has the set code LEA)</small></dd>
|
<dd>[set:lea](#set:lea) <small>(Cards that appear in Alpha, which has the set code LEA)</small></dd>
|
||||||
<dd>[e:lea OR e:leb](#e:lea OR e:leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
|
<dd>[e:lea OR e:leb](#e:lea OR e:leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
|
||||||
|
<dd>[e<8ED](#e<8ED) <small>(Cards that appear before 8th edition)</small></dd>
|
||||||
|
|
||||||
<dt>Negate:</dt>
|
<dt>Negate:</dt>
|
||||||
<dd>[c:wu -c:m](#c:wu -c:m) <small>(Any card that is white or blue, but not multicolored)</small></dd>
|
<dd>[c:wu -c:m](#c:wu -c:m) <small>(Any card that is white or blue, but not multicolored)</small></dd>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
#include <libcockatrice/utility/peglib.h>
|
#include <libcockatrice/utility/peglib.h>
|
||||||
|
|
||||||
static peg::parser search(R"(
|
static peg::parser search(R"(
|
||||||
|
|
@ -19,7 +20,7 @@ SomewhatComplexQueryPart <- [(] QueryPartList [)] / QueryPart
|
||||||
QueryPart <- NotQuery / SetQuery / RarityQuery / CMCQuery / FormatQuery / PowerQuery / ToughnessQuery / ColorQuery / TypeQuery / OracleQuery / FieldQuery / GenericQuery
|
QueryPart <- NotQuery / SetQuery / RarityQuery / CMCQuery / FormatQuery / PowerQuery / ToughnessQuery / ColorQuery / TypeQuery / OracleQuery / FieldQuery / GenericQuery
|
||||||
|
|
||||||
NotQuery <- ('NOT' ws/'-') SomewhatComplexQueryPart
|
NotQuery <- ('NOT' ws/'-') SomewhatComplexQueryPart
|
||||||
SetQuery <- ('e'/'set') [:] FlexStringValue
|
SetQuery <- ('e'/'set') SetExpression / ([:] FlexStringValue)
|
||||||
OracleQuery <- 'o' [:] MatcherString
|
OracleQuery <- 'o' [:] MatcherString
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -64,6 +65,8 @@ RegexMatcherString <- ('\\/' / !'/' .)+
|
||||||
FlexStringValue <- CompactStringSet / String / [(] StringList [)]
|
FlexStringValue <- CompactStringSet / String / [(] StringList [)]
|
||||||
CompactStringSet <- StringListString ([,+] StringListString)+
|
CompactStringSet <- StringListString ([,+] StringListString)+
|
||||||
|
|
||||||
|
SetExpression <- NumericOperator ws? String
|
||||||
|
|
||||||
NumericExpression <- NumericOperator ws? NumericValue
|
NumericExpression <- NumericOperator ws? NumericValue
|
||||||
NumericOperator <- [=:] / <[><!][=]?>
|
NumericOperator <- [=:] / <[><!][=]?>
|
||||||
NumericValue <- [0-9]+
|
NumericValue <- [0-9]+
|
||||||
|
|
@ -101,6 +104,7 @@ static void setupParserRules()
|
||||||
return [=](const CardData &x) -> bool { return matcher(x->getCardType()); };
|
return [=](const CardData &x) -> bool { return matcher(x->getCardType()); };
|
||||||
};
|
};
|
||||||
search["SetQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
search["SetQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||||
|
if (sv.choice() == 1) {
|
||||||
auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||||
return [=](const CardData &x) -> bool {
|
return [=](const CardData &x) -> bool {
|
||||||
QList<QString> sets = x->getSets().keys();
|
QList<QString> sets = x->getSets().keys();
|
||||||
|
|
@ -108,6 +112,18 @@ static void setupParserRules()
|
||||||
auto matchesSet = [&matcher](const QString &set) { return matcher(set); };
|
auto matchesSet = [&matcher](const QString &set) { return matcher(set); };
|
||||||
return std::any_of(sets.begin(), sets.end(), matchesSet);
|
return std::any_of(sets.begin(), sets.end(), matchesSet);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto matcher = std::any_cast<NumberMatcher>(sv[0]);
|
||||||
|
return [=](const CardData &x) -> bool {
|
||||||
|
const auto &sets = x->getSets().values();
|
||||||
|
auto matchesSet = [&](const PrintingInfo &printing) {
|
||||||
|
return printing.getSet()->getEnabled() && matcher(printing.getSet()->getReleaseDate().toJulianDay());
|
||||||
|
};
|
||||||
|
return std::any_of(sets.begin(), sets.end(), [&](const auto &printings) {
|
||||||
|
return std::any_of(printings.begin(), printings.end(), matchesSet);
|
||||||
|
});
|
||||||
|
};
|
||||||
};
|
};
|
||||||
search["Rarity"] = [](const peg::SemanticValues &sv) -> QString {
|
search["Rarity"] = [](const peg::SemanticValues &sv) -> QString {
|
||||||
switch (tolower(std::string(sv.sv())[0])) {
|
switch (tolower(std::string(sv.sv())[0])) {
|
||||||
|
|
@ -247,40 +263,54 @@ static void setupParserRules()
|
||||||
return QString::fromStdString(std::string(sv.sv()));
|
return QString::fromStdString(std::string(sv.sv()));
|
||||||
};
|
};
|
||||||
|
|
||||||
search["NumericExpression"] = [](const peg::SemanticValues &sv) -> NumberMatcher {
|
search["NumericOperator"] = [](const peg::SemanticValues &sv) -> NumberComparer {
|
||||||
const auto arg = std::any_cast<int>(sv[1]);
|
const auto op = QString::fromStdString(std::string(sv.sv()));
|
||||||
const auto op = std::any_cast<QString>(sv[0]);
|
|
||||||
|
|
||||||
if (op == ">") {
|
if (op == ">") {
|
||||||
return [=](const int s) { return s > arg; };
|
return [=](const int s, const int arg) { return s > arg; };
|
||||||
}
|
}
|
||||||
if (op == ">=") {
|
if (op == ">=") {
|
||||||
return [=](const int s) { return s >= arg; };
|
return [=](const int s, const int arg) { return s >= arg; };
|
||||||
}
|
}
|
||||||
if (op == "<") {
|
if (op == "<") {
|
||||||
return [=](const int s) { return s < arg; };
|
return [=](const int s, const int arg) { return s < arg; };
|
||||||
}
|
}
|
||||||
if (op == "<=") {
|
if (op == "<=") {
|
||||||
return [=](const int s) { return s <= arg; };
|
return [=](const int s, const int arg) { return s <= arg; };
|
||||||
}
|
}
|
||||||
if (op == "=") {
|
if (op == "=") {
|
||||||
return [=](const int s) { return s == arg; };
|
return [=](const int s, const int arg) { return s == arg; };
|
||||||
}
|
}
|
||||||
if (op == ":") {
|
if (op == ":") {
|
||||||
return [=](const int s) { return s == arg; };
|
return [=](const int s, const int arg) { return s == arg; };
|
||||||
}
|
}
|
||||||
if (op == "!=") {
|
if (op == "!=") {
|
||||||
return [=](const int s) { return s != arg; };
|
return [=](const int s, const int arg) { return s != arg; };
|
||||||
}
|
}
|
||||||
return [](int) { return false; };
|
return [](int, int) { return false; };
|
||||||
};
|
};
|
||||||
|
|
||||||
search["NumericValue"] = [](const peg::SemanticValues &sv) -> int {
|
search["NumericValue"] = [](const peg::SemanticValues &sv) -> int {
|
||||||
return QString::fromStdString(std::string(sv.sv())).toInt();
|
return QString::fromStdString(std::string(sv.sv())).toInt();
|
||||||
};
|
};
|
||||||
|
|
||||||
search["NumericOperator"] = [](const peg::SemanticValues &sv) -> QString {
|
search["NumericExpression"] = [](const peg::SemanticValues &sv) -> NumberMatcher {
|
||||||
return QString::fromStdString(std::string(sv.sv()));
|
const auto comparer = std::any_cast<NumberComparer>(sv[0]);
|
||||||
|
const auto arg = std::any_cast<int>(sv[1]);
|
||||||
|
return [=](int s) { return comparer(s, arg); };
|
||||||
|
};
|
||||||
|
|
||||||
|
search["SetExpression"] = [](const peg::SemanticValues &sv) -> NumberMatcher {
|
||||||
|
const auto comparer = std::any_cast<NumberComparer>(sv[0]);
|
||||||
|
const auto setCode = std::any_cast<QString>(sv[1]);
|
||||||
|
const auto allSets = CardDatabaseManager::getInstance()->getSetList();
|
||||||
|
for (auto &set : allSets) {
|
||||||
|
if (set->getShortName() == setCode) {
|
||||||
|
const int releaseDate = set->getReleaseDate().toJulianDay();
|
||||||
|
return [=](int s) { return comparer(s, releaseDate); };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [](int) { return false; };
|
||||||
};
|
};
|
||||||
|
|
||||||
search["NormalMatcher"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
search["NormalMatcher"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ typedef CardInfoPtr CardData;
|
||||||
typedef std::function<bool(const CardData &)> Filter;
|
typedef std::function<bool(const CardData &)> Filter;
|
||||||
typedef std::function<bool(const QString &)> StringMatcher;
|
typedef std::function<bool(const QString &)> StringMatcher;
|
||||||
typedef std::function<bool(int)> NumberMatcher;
|
typedef std::function<bool(int)> NumberMatcher;
|
||||||
|
typedef std::function<bool(int, int)> NumberComparer;
|
||||||
|
|
||||||
namespace peg
|
namespace peg
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue