From d31b0445296068e5ec648f3fd5fded56436217b9 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 27 Sep 2025 00:27:15 +0200 Subject: [PATCH] [Card DB] Split out database loading and querying from main class (#6175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Simplify add card. Took 25 minutes Took 8 minutes # Commit time for manual adjustment: # Took 16 minutes Took 7 seconds * Refactor out db loading from card db. Took 39 minutes Took 9 minutes Took 2 minutes Took 17 seconds * Refactor out db queries from card db. Took 42 minutes * Lint. Took 3 minutes * I guess. Took 7 minutes * Tests. Took 15 minutes * I don't understand this. Took 9 minutes * fix linker errors * Rename to querier and promote to QObject Took 39 minutes * Lint. Took 3 minutes --------- Co-authored-by: Lukas Brübach Co-authored-by: ebbit1q --- cockatrice/CMakeLists.txt | 2 + .../src/client/tapped_out_interface.cpp | 2 +- cockatrice/src/database/card_database.cpp | 441 +----------------- cockatrice/src/database/card_database.h | 76 +-- .../src/database/card_database_loader.cpp | 153 ++++++ .../src/database/card_database_loader.h | 57 +++ .../src/database/card_database_manager.cpp | 5 + .../src/database/card_database_manager.h | 2 +- .../src/database/card_database_querier.cpp | 322 +++++++++++++ .../src/database/card_database_querier.h | 54 +++ cockatrice/src/deck/deck_list_model.cpp | 10 +- cockatrice/src/deck/deck_loader.cpp | 11 +- cockatrice/src/deck/deck_stats_interface.cpp | 2 +- cockatrice/src/dialogs/dlg_edit_tokens.cpp | 2 +- .../src/dialogs/dlg_select_set_for_cards.cpp | 23 +- cockatrice/src/filters/deck_filter_string.cpp | 2 +- .../src/game/board/abstract_card_item.cpp | 2 +- .../src/game/deckview/deck_view_container.cpp | 2 +- .../src/game/dialogs/dlg_create_token.cpp | 4 +- cockatrice/src/game/player/menu/card_menu.cpp | 8 +- cockatrice/src/game/player/player_actions.cpp | 17 +- .../card_group_display_widget.cpp | 2 +- .../cards/card_info_display_widget.cpp | 2 +- .../widgets/cards/card_info_frame_widget.cpp | 4 +- .../cards/card_info_picture_widget.cpp | 4 +- .../deck_analytics/mana_base_widget.cpp | 2 +- .../deck_analytics/mana_curve_widget.cpp | 2 +- .../deck_analytics/mana_devotion_widget.cpp | 2 +- .../deck_editor_database_display_widget.cpp | 4 +- .../deck_editor_deck_dock_widget.cpp | 6 +- .../interface/widgets/general/home_widget.cpp | 8 +- .../printing_selector_card_overlay_widget.cpp | 2 +- ...tabase_display_main_type_filter_widget.cpp | 2 +- ...atabase_display_sub_type_filter_widget.cpp | 2 +- .../visual_database_display_widget.cpp | 4 +- .../visual_deck_editor_sample_hand_widget.cpp | 2 +- .../visual_deck_editor_widget.cpp | 4 +- .../deck_preview/deck_preview_widget.cpp | 6 +- .../src/tabs/abstract_tab_deck_editor.cpp | 2 +- ...i_response_card_details_display_widget.cpp | 2 +- ...ponse_commander_details_display_widget.cpp | 2 +- .../src/tabs/api/edhrec/tab_edhrec_main.cpp | 2 +- cockatrice/src/tabs/tab_game.cpp | 2 +- .../deck_list_sort_filter_proxy_model.cpp | 4 +- dbconverter/CMakeLists.txt | 2 + dbconverter/src/main.h | 2 +- tests/carddatabase/CMakeLists.txt | 4 + tests/carddatabase/carddatabase_test.cpp | 6 +- tests/carddatabase/filter_string_test.cpp | 8 +- 49 files changed, 719 insertions(+), 572 deletions(-) create mode 100644 cockatrice/src/database/card_database_loader.cpp create mode 100644 cockatrice/src/database/card_database_loader.h create mode 100644 cockatrice/src/database/card_database_querier.cpp create mode 100644 cockatrice/src/database/card_database_querier.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 11b5275e6..5ab2a066a 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -22,7 +22,9 @@ set(cockatrice_SOURCES src/client/tapped_out_interface.cpp src/client/update_downloader.cpp src/database/card_database.cpp + src/database/card_database_loader.cpp src/database/card_database_manager.cpp + src/database/card_database_querier.cpp src/database/model/card_database_model.cpp src/database/model/card_database_display_model.cpp src/database/model/card/card_completer_proxy_model.cpp diff --git a/cockatrice/src/client/tapped_out_interface.cpp b/cockatrice/src/client/tapped_out_interface.cpp index bea880b27..43ceb6cdd 100644 --- a/cockatrice/src/client/tapped_out_interface.cpp +++ b/cockatrice/src/client/tapped_out_interface.cpp @@ -96,7 +96,7 @@ void TappedOutInterface::analyzeDeck(DeckList *deck) void TappedOutInterface::copyDeckSplitMainAndSide(DeckList &source, DeckList &mainboard, DeckList &sideboard) { auto copyMainOrSide = [this, &mainboard, &sideboard](const auto node, const auto card) { - CardInfoPtr dbCard = cardDatabase.getCardInfo(card->getName()); + CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName()); if (!dbCard || dbCard->getIsToken()) return; diff --git a/cockatrice/src/database/card_database.cpp b/cockatrice/src/database/card_database.cpp index 9ed89a11d..a26445005 100644 --- a/cockatrice/src/database/card_database.cpp +++ b/cockatrice/src/database/card_database.cpp @@ -2,7 +2,6 @@ #include "../picture_loader/picture_loader.h" #include "../settings/cache_settings.h" -#include "../utility/card_set_comparator.h" #include "parser/cockatrice_xml_3.h" #include "parser/cockatrice_xml_4.h" @@ -14,7 +13,6 @@ #include #include #include -#include #include CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded) @@ -22,23 +20,20 @@ CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoa qRegisterMetaType("CardInfoPtr"); qRegisterMetaType("CardSetPtr"); - // add new parsers here - availableParsers << new CockatriceXml4Parser; - availableParsers << new CockatriceXml3Parser; + // create loader and wire it up + loader = new CardDatabaseLoader(this, this); + // re-emit loader signals (so other code doesn't need to know about internals) + connect(loader, &CardDatabaseLoader::loadingFinished, this, &CardDatabase::cardDatabaseLoadingFinished); + connect(loader, &CardDatabaseLoader::loadingFailed, this, &CardDatabase::cardDatabaseLoadingFailed); + connect(loader, &CardDatabaseLoader::newSetsFound, this, &CardDatabase::cardDatabaseNewSetsFound); + connect(loader, &CardDatabaseLoader::allNewSetsEnabled, this, &CardDatabase::cardDatabaseAllNewSetsEnabled); - for (auto &parser : availableParsers) { - connect(parser, &ICardDatabaseParser::addCard, this, &CardDatabase::addCard, Qt::DirectConnection); - connect(parser, &ICardDatabaseParser::addSet, this, &CardDatabase::addSet, Qt::DirectConnection); - } - - connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this, - &CardDatabase::loadCardDatabases); + querier = new CardDatabaseQuerier(this, this); } CardDatabase::~CardDatabase() { clear(); - qDeleteAll(availableParsers); } void CardDatabase::clear() @@ -60,91 +55,14 @@ void CardDatabase::clear() loadStatus = NotLoaded; } -LoadStatus CardDatabase::loadFromFile(const QString &fileName) +void CardDatabase::loadCardDatabases() { - QFile file(fileName); - file.open(QIODevice::ReadOnly); - if (!file.isOpen()) { - return FileError; - } - - for (auto parser : availableParsers) { - file.reset(); - if (parser->getCanParseFile(fileName, file)) { - file.reset(); - parser->parseFile(file); - return Ok; - } - } - - return Invalid; + loadStatus = loader->loadCardDatabases(); } -LoadStatus CardDatabase::loadCardDatabase(const QString &path) +bool CardDatabase::saveCustomTokensToFile() { - auto startTime = QTime::currentTime(); - LoadStatus tempLoadStatus = NotLoaded; - if (!path.isEmpty()) { - QMutexLocker locker(loadFromFileMutex); - tempLoadStatus = loadFromFile(path); - } - - int msecs = startTime.msecsTo(QTime::currentTime()); - qCInfo(CardDatabaseLoadingLog) << "Loaded card database: Path =" << path << "Status =" << tempLoadStatus - << "Cards =" << cards.size() << "Sets =" << sets.size() - << QString("%1ms").arg(msecs); - - return tempLoadStatus; -} - -LoadStatus CardDatabase::loadCardDatabases() -{ - QMutexLocker locker(reloadDatabaseMutex); - qCInfo(CardDatabaseLoadingLog) << "Card Database Loading Started"; - - clear(); // remove old db - - loadStatus = loadCardDatabase(SettingsCache::instance().getCardDatabasePath()); // load main card database - loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database - loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database - - // find all custom card databases, recursively & following symlinks - // then load them alphabetically - auto customPaths = collectCustomDatabasePaths(); - for (int i = 0, n = customPaths.size(); i < n; ++i) { - const auto &path = customPaths.at(i); - qCInfo(CardDatabaseLoadingLog) << "Loading Custom Set" << i << "(" << path << ")"; - loadCardDatabase(path); - } - - // AFTER all the cards have been loaded - - // resolve the reverse-related tags - - refreshCachedReverseRelatedCards(); - - if (loadStatus == Ok) { - checkUnknownSets(); // update deck editors, etc - qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Success"; - emit cardDatabaseLoadingFinished(); - } else { - qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Failed"; - emit cardDatabaseLoadingFailed(); // bring up the settings dialog - } - - return loadStatus; -} - -QStringList CardDatabase::collectCustomDatabasePaths() -{ - QDirIterator it(SettingsCache::instance().getCustomCardDatabasePath(), {"*.xml"}, QDir::Files, - QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); - - QStringList paths; - while (it.hasNext()) - paths << it.next(); - paths.sort(); - return paths; + return loader->saveCustomTokensToFile(); } void CardDatabase::refreshCachedReverseRelatedCards() @@ -210,135 +128,9 @@ void CardDatabase::removeCard(CardInfoPtr card) emit cardRemoved(card); } -/** - * Looks up the cardInfo corresponding to the cardName. - * - * @param cardName The card name to look up - * @return A CardInfoPtr, or null if not corresponding CardInfo is found. - */ -CardInfoPtr CardDatabase::getCardInfo(const QString &cardName) const +void CardDatabase::addSet(CardSetPtr set) { - return cards.value(cardName); -} - -/** - * Looks up the cardInfos for a list of card names. - * - * @param cardNames The card names to look up - * @return A List of CardInfoPtr. Any failed lookups will be ignored and dropped from the resulting list - */ -QList CardDatabase::getCardInfos(const QStringList &cardNames) const -{ - QList cardInfos; - for (const QString &cardName : cardNames) { - CardInfoPtr ptr = cards.value(cardName); - if (ptr) - cardInfos.append(ptr); - } - - return cardInfos; -} - -/** - * Looks up the cards corresponding to the CardRefs. - * If the providerId is empty, will default to the preferred printing. - * If providerId is given but not found, the PrintingInfo will be empty. - * - * @param cardRefs The cards to look up. If providerId is empty for an entry, will default to the preferred printing for - * that entry. If providerId is given but not found, the PrintingInfo will be empty for that entry. - * @return A list of cards. Any failed lookups will be ignored and dropped from the resulting list. - */ -QList CardDatabase::getCards(const QList &cardRefs) const -{ - QList cards; - for (const auto &cardRef : cardRefs) { - ExactCard card = getCard(cardRef); - if (card) - cards.append(card); - } - - return cards; -} - -/** - * Looks up the card corresponding to the CardRef. - * If the providerId is empty, will default to the preferred printing. - * If providerId is given but not found, the PrintingInfo will be empty. - * - * @param cardRef The card to look up. - * @return A specific printing of a card, or empty if not found. - */ -ExactCard CardDatabase::getCard(const CardRef &cardRef) const -{ - auto info = getCardInfo(cardRef.name); - if (info.isNull()) { - return {}; - } - - if (cardRef.providerId.isEmpty() || cardRef.providerId.isNull()) { - return ExactCard(info, getPreferredPrinting(info)); - } - - return ExactCard(info, findPrintingWithId(info, cardRef.providerId)); -} - -CardInfoPtr CardDatabase::getCardBySimpleName(const QString &cardName) const -{ - return simpleNameCards.value(CardInfo::simplifyName(cardName)); -} - -CardInfoPtr CardDatabase::lookupCardByName(const QString &name) const -{ - if (auto info = getCardInfo(name)) - return info; - if (auto info = getCardBySimpleName(name)) - return info; - return getCardBySimpleName(CardInfo::simplifyName(name)); -} - -/** - * Looks up the card by CardRef, simplifying the name if required. - * If the providerId is empty, will default to the preferred printing. - * If providerId is given but not found, the PrintingInfo will be empty. - * - * @param cardRef The card to look up. - * @return A specific printing of a card, or empty if not found. - */ -ExactCard CardDatabase::guessCard(const CardRef &cardRef) const -{ - auto card = lookupCardByName(cardRef.name); - auto printing = - cardRef.providerId.isEmpty() ? getPreferredPrinting(card) : findPrintingWithId(card, cardRef.providerId); - - return ExactCard(card, printing); -} - -ExactCard CardDatabase::getRandomCard() -{ - if (cards.isEmpty()) - return {}; - - const auto keys = cards.keys(); - int randomIndex = QRandomGenerator::global()->bounded(keys.size()); - const QString &randomKey = keys.at(randomIndex); - CardInfoPtr randomCard = getCardInfo(randomKey); - - return ExactCard{randomCard, getPreferredPrinting(randomCard)}; -} - -ExactCard CardDatabase::getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const -{ - // The source card does not have a printing defined, which means we can't get a card from the same set. - if (otherPrinting == PrintingInfo()) { - return getCard({cardName}); - } - - // The source card does have a printing defined, which means we can attempt to get a card from the same set. - PrintingInfo relatedPrinting = getSpecificPrinting(cardName, otherPrinting.getSet()->getCorrectedShortName(), ""); - ExactCard relatedCard(guessCard({cardName}).getCardPtr(), relatedPrinting); - - // If we didn't find a card from the same set, just try to find any card with the same name. - return relatedCard ? relatedCard : getCard({cardName}); + sets.insert(set->getShortName(), set); } CardSetPtr CardDatabase::getSet(const QString &setName) @@ -352,11 +144,6 @@ CardSetPtr CardDatabase::getSet(const QString &setName) } } -void CardDatabase::addSet(CardSetPtr set) -{ - sets.insert(set->getShortName(), set); -} - SetList CardDatabase::getSetList() const { SetList result; @@ -366,187 +153,6 @@ SetList CardDatabase::getSetList() const return result; } -/** - * Finds the PrintingInfo in the cardInfo that has the given uuid field. - * - * @param cardInfo The CardInfo to search - * @param providerId The uuid to look for - * @return The PrintingInfo, or a default-constructed PrintingInfo if not found. - */ -PrintingInfo CardDatabase::findPrintingWithId(const CardInfoPtr &cardInfo, const QString &providerId) -{ - for (const auto &printings : cardInfo->getSets()) { - for (const auto &printing : printings) { - if (printing.getUuid() == providerId) { - return printing; - } - } - } - - return PrintingInfo(); -} - -PrintingInfo CardDatabase::getSpecificPrinting(const CardRef &cardRef) const -{ - CardInfoPtr cardInfo = getCardInfo(cardRef.name); - if (!cardInfo) { - return PrintingInfo(nullptr); - } - - return findPrintingWithId(cardInfo, cardRef.providerId); -} - -PrintingInfo CardDatabase::getSpecificPrinting(const QString &cardName, - const QString &setShortName, - const QString &collectorNumber) const -{ - CardInfoPtr cardInfo = getCardInfo(cardName); - if (!cardInfo) { - return PrintingInfo(nullptr); - } - - SetToPrintingsMap setMap = cardInfo->getSets(); - if (setMap.empty()) { - return PrintingInfo(nullptr); - } - - for (const auto &printings : setMap) { - for (auto &cardInfoForSet : printings) { - if (!collectorNumber.isEmpty()) { - if (cardInfoForSet.getSet()->getShortName() == setShortName && - cardInfoForSet.getProperty("num") == collectorNumber) { - return cardInfoForSet; - } - } else { - if (cardInfoForSet.getSet()->getShortName() == setShortName) { - return cardInfoForSet; - } - } - } - } - - return PrintingInfo(nullptr); -} - -/** - * Gets the card representing the preferred printing of the cardInfo - * - * @param cardInfo The cardInfo to find the preferred printing for - * @return A specific printing of a card - */ -ExactCard CardDatabase::getPreferredCard(const CardInfoPtr &cardInfo) const -{ - return ExactCard(cardInfo, getPreferredPrinting(cardInfo)); -} - -bool CardDatabase::isPreferredPrinting(const CardRef &cardRef) const -{ - if (cardRef.providerId.startsWith("card_")) { - return cardRef.providerId == - QLatin1String("card_") + cardRef.name + QString("_") + getPreferredPrintingProviderId(cardRef.name); - } - return cardRef.providerId == getPreferredPrintingProviderId(cardRef.name); -} - -PrintingInfo CardDatabase::getPreferredPrinting(const QString &cardName) const -{ - CardInfoPtr cardInfo = getCardInfo(cardName); - return getPreferredPrinting(cardInfo); -} - -PrintingInfo CardDatabase::getPreferredPrinting(const CardInfoPtr &cardInfo) const -{ - if (!cardInfo) { - return PrintingInfo(nullptr); - } - - SetToPrintingsMap setMap = cardInfo->getSets(); - if (setMap.empty()) { - return PrintingInfo(nullptr); - } - - CardSetPtr preferredSet = nullptr; - PrintingInfo preferredPrinting; - SetPriorityComparator comparator; - - for (const auto &printings : setMap) { - for (auto &printing : printings) { - CardSetPtr currentSet = printing.getSet(); - if (!preferredSet || comparator(currentSet, preferredSet)) { - preferredSet = currentSet; - preferredPrinting = printing; - } - } - } - - if (preferredSet) { - return preferredPrinting; - } - - return PrintingInfo(nullptr); -} - -QString CardDatabase::getPreferredPrintingProviderId(const QString &cardName) const -{ - PrintingInfo preferredPrinting = getPreferredPrinting(cardName); - QString uuid = preferredPrinting.getUuid(); - if (!uuid.isEmpty()) { - return uuid; - } - - CardInfoPtr defaultCardInfo = getCardInfo(cardName); - if (defaultCardInfo.isNull()) { - return cardName; - } - return defaultCardInfo->getName(); -} - -QStringList CardDatabase::getAllMainCardTypes() const -{ - QSet types; - for (const auto &card : cards.values()) { - types.insert(card->getMainCardType()); - } - return types.values(); -} - -QMap CardDatabase::getAllMainCardTypesWithCount() const -{ - QMap typeCounts; - - for (const auto &card : cards.values()) { - QString type = card->getMainCardType(); - typeCounts[type]++; - } - - return typeCounts; -} - -QMap CardDatabase::getAllSubCardTypesWithCount() const -{ - QMap typeCounts; - - for (const auto &card : cards.values()) { - QString type = card->getCardType(); - - QStringList parts = type.split(" — "); - - if (parts.size() > 1) { // Ensure there are subtypes -#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - QStringList subtypes = parts[1].split(" ", Qt::SkipEmptyParts); -#else - QStringList subtypes = parts[1].split(" ", QString::SkipEmptyParts); -#endif - - for (const QString &subtype : subtypes) { - typeCounts[subtype]++; - } - } - } - - return typeCounts; -} - void CardDatabase::checkUnknownSets() { auto _sets = getSetList(); @@ -592,22 +198,3 @@ void CardDatabase::notifyEnabledSetsChanged() // inform the carddatabasemodels that they need to re-check their list of cards emit cardDatabaseEnabledSetsChanged(); } - -bool CardDatabase::saveCustomTokensToFile() -{ - QString fileName = SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml"; - - SetNameMap tmpSets; - CardSetPtr customTokensSet = getSet(CardSet::TOKENS_SETNAME); - tmpSets.insert(CardSet::TOKENS_SETNAME, customTokensSet); - - CardNameMap tmpCards; - for (const CardInfoPtr &card : cards) { - if (card->getSets().contains(CardSet::TOKENS_SETNAME)) { - tmpCards.insert(card->getName(), card); - } - } - - availableParsers.first()->saveToFile(tmpSets, tmpCards, fileName); - return true; -} diff --git a/cockatrice/src/database/card_database.h b/cockatrice/src/database/card_database.h index d3d98d368..a6941ee5b 100644 --- a/cockatrice/src/database/card_database.h +++ b/cockatrice/src/database/card_database.h @@ -3,6 +3,8 @@ #include "../card/exact_card.h" #include "../common/card_ref.h" +#include "card_database_loader.h" +#include "card_database_querier.h" #include #include @@ -14,20 +16,6 @@ #include inline Q_LOGGING_CATEGORY(CardDatabaseLog, "card_database"); -inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading"); -inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure"); - -class ICardDatabaseParser; - -enum LoadStatus -{ - Ok, - VersionTooOld, - Invalid, - NotLoaded, - FileError, - NoCards -}; class CardDatabase : public QObject { @@ -48,79 +36,50 @@ protected: */ SetNameMap sets; + // loader responsible for file discovery & parsing + CardDatabaseLoader *loader; + LoadStatus loadStatus; - QVector availableParsers; + CardDatabaseQuerier *querier; private: void checkUnknownSets(); void refreshCachedReverseRelatedCards(); - QBasicMutex *reloadDatabaseMutex = new QBasicMutex(), *clearDatabaseMutex = new QBasicMutex(), - *loadFromFileMutex = new QBasicMutex(), *addCardMutex = new QBasicMutex(), + QBasicMutex *clearDatabaseMutex = new QBasicMutex(), *addCardMutex = new QBasicMutex(), *removeCardMutex = new QBasicMutex(); public: explicit CardDatabase(QObject *parent = nullptr); ~CardDatabase() override; - void clear(); + void removeCard(CardInfoPtr card); + void clear(); - [[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const; - [[nodiscard]] QList getCardInfos(const QStringList &cardNames) const; - - QList getCards(const QList &cardRefs) const; - [[nodiscard]] ExactCard getCard(const CardRef &cardRef) const; - - [[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &cardInfo) const; - - static PrintingInfo findPrintingWithId(const CardInfoPtr &cardInfo, const QString &providerId); - [[nodiscard]] PrintingInfo getPreferredPrinting(const QString &cardName) const; - [[nodiscard]] PrintingInfo getPreferredPrinting(const CardInfoPtr &cardInfo) const; - [[nodiscard]] PrintingInfo getSpecificPrinting(const CardRef &cardRef) const; - PrintingInfo - getSpecificPrinting(const QString &cardName, const QString &setShortName, const QString &collectorNumber) const; - QString getPreferredPrintingProviderId(const QString &cardName) const; - bool isPreferredPrinting(const CardRef &cardRef) const; - ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const; - - [[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const; - [[nodiscard]] ExactCard getRandomCard(); - - /* - * Get a card by its simple name. The name will be simplified in this - * function, so you don't need to simplify it beforehand. - */ - [[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const; - CardInfoPtr lookupCardByName(const QString &name) const; - - CardSetPtr getSet(const QString &setName); const CardNameMap &getCardList() const { return cards; } + CardSetPtr getSet(const QString &setName); SetList getSetList() const; - CardInfoPtr getCardFromMap(const CardNameMap &cardMap, const QString &cardName) const; - LoadStatus loadFromFile(const QString &fileName); - bool saveCustomTokensToFile(); - QStringList getAllMainCardTypes() const; - QMap getAllMainCardTypesWithCount() const; - QMap getAllSubCardTypesWithCount() const; LoadStatus getLoadStatus() const { return loadStatus; } + CardDatabaseQuerier *query() const + { + return querier; + } void enableAllUnknownSets(); void markAllSetsAsKnown(); void notifyEnabledSetsChanged(); - static QStringList collectCustomDatabasePaths(); public slots: - LoadStatus loadCardDatabases(); void addCard(CardInfoPtr card); void addSet(CardSetPtr set); -protected slots: - LoadStatus loadCardDatabase(const QString &path); + void loadCardDatabases(); + bool saveCustomTokensToFile(); signals: void cardDatabaseLoadingFinished(); void cardDatabaseLoadingFailed(); @@ -129,6 +88,9 @@ signals: void cardDatabaseEnabledSetsChanged(); void cardAdded(CardInfoPtr card); void cardRemoved(CardInfoPtr card); + + friend class CardDatabaseLoader; + friend class CardDatabaseQuerier; }; #endif diff --git a/cockatrice/src/database/card_database_loader.cpp b/cockatrice/src/database/card_database_loader.cpp new file mode 100644 index 000000000..fbb3e6b67 --- /dev/null +++ b/cockatrice/src/database/card_database_loader.cpp @@ -0,0 +1,153 @@ +#include "card_database_loader.h" + +#include "../settings/cache_settings.h" +#include "card_database.h" +#include "parser/cockatrice_xml_3.h" +#include "parser/cockatrice_xml_4.h" + +#include +#include +#include +#include + +CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObject(parent), database(db) +{ + // instantiate available parsers here and connect them to the database + availableParsers << new CockatriceXml4Parser; + availableParsers << new CockatriceXml3Parser; + + for (auto *p : availableParsers) { + // connect parser outputs to the database adders + connect(p, &ICardDatabaseParser::addCard, database, &CardDatabase::addCard, Qt::DirectConnection); + connect(p, &ICardDatabaseParser::addSet, database, &CardDatabase::addSet, Qt::DirectConnection); + } + + // when SettingsCache's path changes, trigger reloads + connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this, + &CardDatabaseLoader::loadCardDatabases); +} + +CardDatabaseLoader::~CardDatabaseLoader() +{ + qDeleteAll(availableParsers); + availableParsers.clear(); +} + +LoadStatus CardDatabaseLoader::loadFromFile(const QString &fileName) +{ + QFile file(fileName); + file.open(QIODevice::ReadOnly); + if (!file.isOpen()) { + return FileError; + } + + for (auto parser : availableParsers) { + file.reset(); + if (parser->getCanParseFile(fileName, file)) { + file.reset(); + parser->parseFile(file); + return Ok; + } + } + + return Invalid; +} + +LoadStatus CardDatabaseLoader::loadCardDatabase(const QString &path) +{ + auto startTime = QTime::currentTime(); + LoadStatus tempLoadStatus = NotLoaded; + if (!path.isEmpty()) { + QMutexLocker locker(loadFromFileMutex); + tempLoadStatus = loadFromFile(path); + } + + int msecs = startTime.msecsTo(QTime::currentTime()); + qCInfo(CardDatabaseLoadingLog) << "Loaded card database: Path =" << path << "Status =" << tempLoadStatus + << "Cards =" << (database ? database->cards.size() : 0) + << "Sets =" << (database ? database->sets.size() : 0) << QString("%1ms").arg(msecs); + + return tempLoadStatus; +} + +LoadStatus CardDatabaseLoader::loadCardDatabases() +{ + QMutexLocker locker(reloadDatabaseMutex); + + if (!database) { + qCWarning(CardDatabaseLoadingLog) << "Loader has no database pointer"; + emit loadingFailed(); + return FileError; + } + emit loadingStarted(); + qCInfo(CardDatabaseLoadingLog) << "Card Database Loading Started"; + + database->clear(); // remove old db + + LoadStatus loadStatus = + loadCardDatabase(SettingsCache::instance().getCardDatabasePath()); // load main card database + loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database + loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database + + // find all custom card databases, recursively & following symlinks + // then load them alphabetically + const QStringList customPaths = collectCustomDatabasePaths(); + for (int i = 0; i < customPaths.size(); ++i) { + const auto &p = customPaths.at(i); + qCInfo(CardDatabaseLoadingLog) << "Loading Custom Set" << i << "(" << p << ")"; + loadCardDatabase(p); + } + + // AFTER all the cards have been loaded + + // resolve the reverse-related tags + + database->refreshCachedReverseRelatedCards(); + + if (loadStatus == Ok) { + database->checkUnknownSets(); // update deck editors, etc + qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Success"; + emit loadingFinished(); + } else { + qCInfo(CardDatabaseLoadingSuccessOrFailureLog) << "Card Database Loading Failed"; + emit loadingFailed(); // bring up the settings dialog + } + + return loadStatus; +} + +QStringList CardDatabaseLoader::collectCustomDatabasePaths() const +{ + QDirIterator it(SettingsCache::instance().getCustomCardDatabasePath(), {"*.xml"}, QDir::Files, + QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); + + QStringList paths; + while (it.hasNext()) + paths << it.next(); + paths.sort(); + return paths; +} + +bool CardDatabaseLoader::saveCustomTokensToFile() +{ + if (!database) { + qCWarning(CardDatabaseLog) << "saveCustomTokensToFile: database pointer missing"; + return false; + } + + QString fileName = SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml"; + + SetNameMap tmpSets; + CardSetPtr customTokensSet = database->getSet(CardSet::TOKENS_SETNAME); + tmpSets.insert(CardSet::TOKENS_SETNAME, customTokensSet); + + CardNameMap tmpCards; + for (const CardInfoPtr &card : database->cards) { + if (card->getSets().contains(CardSet::TOKENS_SETNAME)) { + tmpCards.insert(card->getName(), card); + } + } + + availableParsers.first()->saveToFile(tmpSets, tmpCards, fileName); + return true; +} \ No newline at end of file diff --git a/cockatrice/src/database/card_database_loader.h b/cockatrice/src/database/card_database_loader.h new file mode 100644 index 000000000..37d3c4d75 --- /dev/null +++ b/cockatrice/src/database/card_database_loader.h @@ -0,0 +1,57 @@ +#ifndef COCKATRICE_CARD_DATABASE_LOADER_H +#define COCKATRICE_CARD_DATABASE_LOADER_H + +#include +#include +#include +#include + +inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading"); +inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure"); + +class CardDatabase; +class ICardDatabaseParser; + +enum LoadStatus +{ + Ok, + VersionTooOld, + Invalid, + NotLoaded, + FileError, + NoCards +}; + +class CardDatabaseLoader : public QObject +{ + Q_OBJECT +public: + explicit CardDatabaseLoader(QObject *parent, CardDatabase *db); + ~CardDatabaseLoader() override; + +public slots: + LoadStatus loadCardDatabases(); // discover & load the configured databases + LoadStatus loadCardDatabase(const QString &path); // load a single file + bool saveCustomTokensToFile(); // write tokens to custom DB path + +signals: + void loadingStarted(); + void loadingFinished(); + void loadingFailed(); + void newSetsFound(int numSets, const QStringList &setNames); + void allNewSetsEnabled(); + +private: + LoadStatus loadFromFile(const QString &fileName); // internal helper + QStringList collectCustomDatabasePaths() const; + + CardDatabase *database; // non-owning pointer to the container + + // parsers + QList availableParsers; + + QBasicMutex *loadFromFileMutex = new QBasicMutex(); + QBasicMutex *reloadDatabaseMutex = new QBasicMutex(); +}; + +#endif // COCKATRICE_CARD_DATABASE_LOADER_H diff --git a/cockatrice/src/database/card_database_manager.cpp b/cockatrice/src/database/card_database_manager.cpp index 3036402f0..4ffe0cc70 100644 --- a/cockatrice/src/database/card_database_manager.cpp +++ b/cockatrice/src/database/card_database_manager.cpp @@ -4,4 +4,9 @@ CardDatabase *CardDatabaseManager::getInstance() { static CardDatabase instance; // Created only once, on first access return &instance; +} + +CardDatabaseQuerier *CardDatabaseManager::query() +{ + return getInstance()->query(); } \ No newline at end of file diff --git a/cockatrice/src/database/card_database_manager.h b/cockatrice/src/database/card_database_manager.h index f257dcdef..c87e04888 100644 --- a/cockatrice/src/database/card_database_manager.h +++ b/cockatrice/src/database/card_database_manager.h @@ -1,4 +1,3 @@ - #ifndef CARD_DATABASE_ACCESSOR_H #define CARD_DATABASE_ACCESSOR_H @@ -14,6 +13,7 @@ public: // Static method to access the singleton instance static CardDatabase *getInstance(); + static CardDatabaseQuerier *query(); private: CardDatabaseManager() = default; // Private constructor diff --git a/cockatrice/src/database/card_database_querier.cpp b/cockatrice/src/database/card_database_querier.cpp new file mode 100644 index 000000000..68cc39c9d --- /dev/null +++ b/cockatrice/src/database/card_database_querier.cpp @@ -0,0 +1,322 @@ +#include "card_database_querier.h" + +#include "../utility/card_set_comparator.h" +#include "card_database.h" + +#include + +CardDatabaseQuerier::CardDatabaseQuerier(QObject *_parent, const CardDatabase *_db) : QObject(_parent), db(_db) +{ +} + +/** + * Looks up the cardInfo corresponding to the cardName. + * + * @param cardName The card name to look up + * @return A CardInfoPtr, or null if not corresponding CardInfo is found. + */ +CardInfoPtr CardDatabaseQuerier::getCardInfo(const QString &cardName) const +{ + return db->cards.value(cardName); +} + +/** + * Looks up the cardInfos for a list of card names. + * + * @param cardNames The card names to look up + * @return A List of CardInfoPtr. Any failed lookups will be ignored and dropped from the resulting list + */ +QList CardDatabaseQuerier::getCardInfos(const QStringList &cardNames) const +{ + QList cardInfos; + for (const QString &cardName : cardNames) { + CardInfoPtr ptr = db->cards.value(cardName); + if (ptr) + cardInfos.append(ptr); + } + + return cardInfos; +} + +CardInfoPtr CardDatabaseQuerier::getCardBySimpleName(const QString &cardName) const +{ + return db->simpleNameCards.value(CardInfo::simplifyName(cardName)); +} + +CardInfoPtr CardDatabaseQuerier::lookupCardByName(const QString &name) const +{ + if (auto info = getCardInfo(name)) + return info; + if (auto info = getCardBySimpleName(name)) + return info; + return getCardBySimpleName(CardInfo::simplifyName(name)); +} + +/** + * Looks up the cards corresponding to the CardRefs. + * If the providerId is empty, will default to the preferred printing. + * If providerId is given but not found, the PrintingInfo will be empty. + * + * @param cardRefs The cards to look up. If providerId is empty for an entry, will default to the preferred printing for + * that entry. If providerId is given but not found, the PrintingInfo will be empty for that entry. + * @return A list of cards. Any failed lookups will be ignored and dropped from the resulting list. + */ +QList CardDatabaseQuerier::getCards(const QList &cardRefs) const +{ + QList cards; + for (const auto &cardRef : cardRefs) { + ExactCard card = getCard(cardRef); + if (card) + cards.append(card); + } + + return cards; +} + +/** + * Looks up the card corresponding to the CardRef. + * If the providerId is empty, will default to the preferred printing. + * If providerId is given but not found, the PrintingInfo will be empty. + * + * @param cardRef The card to look up. + * @return A specific printing of a card, or empty if not found. + */ +ExactCard CardDatabaseQuerier::getCard(const CardRef &cardRef) const +{ + auto info = getCardInfo(cardRef.name); + if (info.isNull()) { + return {}; + } + + if (cardRef.providerId.isEmpty() || cardRef.providerId.isNull()) { + return ExactCard(info, getPreferredPrinting(info)); + } + + return ExactCard(info, findPrintingWithId(info, cardRef.providerId)); +} + +/** + * Looks up the card by CardRef, simplifying the name if required. + * If the providerId is empty, will default to the preferred printing. + * If providerId is given but not found, the PrintingInfo will be empty. + * + * @param cardRef The card to look up. + * @return A specific printing of a card, or empty if not found. + */ +ExactCard CardDatabaseQuerier::guessCard(const CardRef &cardRef) const +{ + auto card = lookupCardByName(cardRef.name); + auto printing = + cardRef.providerId.isEmpty() ? getPreferredPrinting(card) : findPrintingWithId(card, cardRef.providerId); + + return ExactCard(card, printing); +} + +ExactCard CardDatabaseQuerier::getRandomCard() const +{ + if (db->cards.isEmpty()) + return {}; + + const auto keys = db->cards.keys(); + int randomIndex = QRandomGenerator::global()->bounded(keys.size()); + const QString &randomKey = keys.at(randomIndex); + CardInfoPtr randomCard = getCardInfo(randomKey); + + return ExactCard{randomCard, getPreferredPrinting(randomCard)}; +} + +ExactCard CardDatabaseQuerier::getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const +{ + // The source card does not have a printing defined, which means we can't get a card from the same set. + if (otherPrinting == PrintingInfo()) { + return getCard({cardName}); + } + + // The source card does have a printing defined, which means we can attempt to get a card from the same set. + PrintingInfo relatedPrinting = getSpecificPrinting(cardName, otherPrinting.getSet()->getCorrectedShortName(), ""); + ExactCard relatedCard(guessCard({cardName}).getCardPtr(), relatedPrinting); + + // If we didn't find a card from the same set, just try to find any card with the same name. + return relatedCard ? relatedCard : getCard({cardName}); +} + +/** + * Finds the PrintingInfo in the cardInfo that has the given uuid field. + * + * @param cardInfo The CardInfo to search + * @param providerId The uuid to look for + * @return The PrintingInfo, or a default-constructed PrintingInfo if not found. + */ +PrintingInfo CardDatabaseQuerier::findPrintingWithId(const CardInfoPtr &cardInfo, const QString &providerId) const +{ + for (const auto &printings : cardInfo->getSets()) { + for (const auto &printing : printings) { + if (printing.getUuid() == providerId) { + return printing; + } + } + } + + return PrintingInfo(); +} + +PrintingInfo CardDatabaseQuerier::getSpecificPrinting(const CardRef &cardRef) const +{ + CardInfoPtr cardInfo = getCardInfo(cardRef.name); + if (!cardInfo) { + return PrintingInfo(nullptr); + } + + return findPrintingWithId(cardInfo, cardRef.providerId); +} + +PrintingInfo CardDatabaseQuerier::getSpecificPrinting(const QString &cardName, + const QString &setShortName, + const QString &collectorNumber) const +{ + CardInfoPtr cardInfo = getCardInfo(cardName); + if (!cardInfo) { + return PrintingInfo(nullptr); + } + + SetToPrintingsMap setMap = cardInfo->getSets(); + if (setMap.empty()) { + return PrintingInfo(nullptr); + } + + for (const auto &printings : setMap) { + for (auto &cardInfoForSet : printings) { + if (!collectorNumber.isEmpty()) { + if (cardInfoForSet.getSet()->getShortName() == setShortName && + cardInfoForSet.getProperty("num") == collectorNumber) { + return cardInfoForSet; + } + } else { + if (cardInfoForSet.getSet()->getShortName() == setShortName) { + return cardInfoForSet; + } + } + } + } + + return PrintingInfo(nullptr); +} + +/** + * Gets the card representing the preferred printing of the cardInfo + * + * @param cardInfo The cardInfo to find the preferred printing for + * @return A specific printing of a card + */ +ExactCard CardDatabaseQuerier::getPreferredCard(const CardInfoPtr &cardInfo) const +{ + return ExactCard(cardInfo, getPreferredPrinting(cardInfo)); +} + +bool CardDatabaseQuerier::isPreferredPrinting(const CardRef &cardRef) const +{ + if (cardRef.providerId.startsWith("card_")) { + return cardRef.providerId == + QLatin1String("card_") + cardRef.name + QString("_") + getPreferredPrintingProviderId(cardRef.name); + } + return cardRef.providerId == getPreferredPrintingProviderId(cardRef.name); +} + +PrintingInfo CardDatabaseQuerier::getPreferredPrinting(const QString &cardName) const +{ + CardInfoPtr cardInfo = getCardInfo(cardName); + return getPreferredPrinting(cardInfo); +} + +PrintingInfo CardDatabaseQuerier::getPreferredPrinting(const CardInfoPtr &cardInfo) const +{ + if (!cardInfo) { + return PrintingInfo(nullptr); + } + + SetToPrintingsMap setMap = cardInfo->getSets(); + if (setMap.empty()) { + return PrintingInfo(nullptr); + } + + CardSetPtr preferredSet = nullptr; + PrintingInfo preferredPrinting; + SetPriorityComparator comparator; + + for (const auto &printings : setMap) { + for (auto &printing : printings) { + CardSetPtr currentSet = printing.getSet(); + if (!preferredSet || comparator(currentSet, preferredSet)) { + preferredSet = currentSet; + preferredPrinting = printing; + } + } + } + + if (preferredSet) { + return preferredPrinting; + } + + return PrintingInfo(nullptr); +} + +QString CardDatabaseQuerier::getPreferredPrintingProviderId(const QString &cardName) const +{ + PrintingInfo preferredPrinting = getPreferredPrinting(cardName); + QString uuid = preferredPrinting.getUuid(); + if (!uuid.isEmpty()) { + return uuid; + } + + CardInfoPtr defaultCardInfo = getCardInfo(cardName); + if (defaultCardInfo.isNull()) { + return cardName; + } + return defaultCardInfo->getName(); +} + +QStringList CardDatabaseQuerier::getAllMainCardTypes() const +{ + QSet types; + for (const auto &card : db->cards.values()) { + types.insert(card->getMainCardType()); + } + return types.values(); +} + +QMap CardDatabaseQuerier::getAllMainCardTypesWithCount() const +{ + QMap typeCounts; + + for (const auto &card : db->cards.values()) { + QString type = card->getMainCardType(); + typeCounts[type]++; + } + + return typeCounts; +} + +QMap CardDatabaseQuerier::getAllSubCardTypesWithCount() const +{ + QMap typeCounts; + + for (const auto &card : db->cards.values()) { + QString type = card->getCardType(); + + QStringList parts = type.split(" — "); + + if (parts.size() > 1) { // Ensure there are subtypes +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + QStringList subtypes = parts[1].split(" ", Qt::SkipEmptyParts); +#else + QStringList subtypes = parts[1].split(" ", QString::SkipEmptyParts); +#endif + + for (const QString &subtype : subtypes) { + typeCounts[subtype]++; + } + } + } + + return typeCounts; +} \ No newline at end of file diff --git a/cockatrice/src/database/card_database_querier.h b/cockatrice/src/database/card_database_querier.h new file mode 100644 index 000000000..26c601333 --- /dev/null +++ b/cockatrice/src/database/card_database_querier.h @@ -0,0 +1,54 @@ +#ifndef COCKATRICE_CARD_DATABASE_QUERIER_H +#define COCKATRICE_CARD_DATABASE_QUERIER_H + +#include "../card/exact_card.h" +#include "../common/card_ref.h" + +#include + +class CardDatabase; +class CardDatabaseQuerier : public QObject +{ + Q_OBJECT + +public: + explicit CardDatabaseQuerier(QObject *parent, const CardDatabase *db); + + [[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const; + [[nodiscard]] QList getCardInfos(const QStringList &cardNames) const; + + /* + * Get a card by its simple name. The name will be simplified in this + * function, so you don't need to simplify it beforehand. + */ + [[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const; + + [[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const; + [[nodiscard]] ExactCard getCard(const CardRef &cardRef) const; + [[nodiscard]] QList getCards(const QList &cardRefs) const; + + [[nodiscard]] ExactCard getRandomCard() const; + [[nodiscard]] ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const; + + [[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &card) const; + [[nodiscard]] bool isPreferredPrinting(const CardRef &cardRef) const; + [[nodiscard]] PrintingInfo getPreferredPrinting(const CardInfoPtr &card) const; + [[nodiscard]] PrintingInfo getPreferredPrinting(const QString &cardName) const; + [[nodiscard]] QString getPreferredPrintingProviderId(const QString &cardName) const; + + [[nodiscard]] PrintingInfo getSpecificPrinting(const CardRef &cardRef) const; + [[nodiscard]] PrintingInfo + getSpecificPrinting(const QString &cardName, const QString &setCode, const QString &collectorNumber) const; + [[nodiscard]] PrintingInfo findPrintingWithId(const CardInfoPtr &card, const QString &providerId) const; + + [[nodiscard]] QStringList getAllMainCardTypes() const; + [[nodiscard]] QMap getAllMainCardTypesWithCount() const; + [[nodiscard]] QMap getAllSubCardTypesWithCount() const; + +private: + const CardDatabase *db; + + CardInfoPtr lookupCardByName(const QString &name) const; +}; + +#endif // COCKATRICE_CARD_DATABASE_QUERIER_H diff --git a/cockatrice/src/deck/deck_list_model.cpp b/cockatrice/src/deck/deck_list_model.cpp index 0733b2e69..4ff16378c 100644 --- a/cockatrice/src/deck/deck_list_model.cpp +++ b/cockatrice/src/deck/deck_list_model.cpp @@ -66,7 +66,7 @@ void DeckListModel::rebuildTree() continue; } - CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName()); + CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); QString groupCriteria = getGroupCriteriaForCard(info); auto *groupNode = dynamic_cast(node->findChild(groupCriteria)); @@ -341,7 +341,7 @@ DecklistModelCardNode *DeckListModel::findCardNode(const QString &cardName, return nullptr; } - CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(cardName); + CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(cardName); if (!info) { return nullptr; } @@ -371,7 +371,7 @@ QModelIndex DeckListModel::findCard(const QString &cardName, QModelIndex DeckListModel::addPreferredPrintingCard(const QString &cardName, const QString &zoneName, bool abAddAnyway) { - ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName}); + ExactCard card = CardDatabaseManager::query()->getCard({cardName}); if (!card) { if (abAddAnyway) { @@ -566,7 +566,7 @@ QList DeckListModel::getCards() const if (!currentCard) continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); + ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef()); if (card) { cards.append(card); } else { @@ -599,7 +599,7 @@ QList DeckListModel::getCardsForZone(const QString &zoneName) const if (!currentCard) continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); + ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef()); if (card) { cards.append(card); } else { diff --git a/cockatrice/src/deck/deck_loader.cpp b/cockatrice/src/deck/deck_loader.cpp index b2aeb1642..8e98422a6 100644 --- a/cockatrice/src/deck/deck_loader.cpp +++ b/cockatrice/src/deck/deck_loader.cpp @@ -282,7 +282,7 @@ QString DeckLoader::exportDeckToDecklist(DecklistWebsite website) // Set up the function to call auto formatDeckListForExport = [&mainBoardCards, &sideBoardCards](const auto *node, const auto *card) { // Get the card name - CardInfoPtr dbCard = CardDatabaseManager::getInstance()->getCardInfo(card->getName()); + CardInfoPtr dbCard = CardDatabaseManager::query()->getCardInfo(card->getName()); if (!dbCard || dbCard->getIsToken()) { // If it's a token, we don't care about the card. return; @@ -325,7 +325,7 @@ struct SetProviderIdToPreferred void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const { Q_UNUSED(node); - PrintingInfo preferredPrinting = CardDatabaseManager::getInstance()->getPreferredPrinting(card->getName()); + PrintingInfo preferredPrinting = CardDatabaseManager::query()->getPreferredPrinting(card->getName()); QString providerId = preferredPrinting.getUuid(); QString setShortName = preferredPrinting.getSet()->getShortName(); QString collectorNumber = preferredPrinting.getProperty("num"); @@ -359,6 +359,7 @@ void DeckLoader::resolveSetNameAndNumberToProviderID() // Retrieve the providerId based on setName and collectorNumber QString providerId = CardDatabaseManager::getInstance() + ->query() ->getSpecificPrinting(card->getName(), card->getCardSetShortName(), card->getCardCollectorNumber()) .getUuid(); @@ -468,7 +469,7 @@ void DeckLoader::saveToStream_DeckZone(QTextStream &out, for (int j = 0; j < zoneNode->size(); j++) { auto *card = dynamic_cast(zoneNode->at(j)); - CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(card->getName()); + CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(card->getName()); QString cardType = info ? info->getMainCardType() : "unknown"; cardsByType.insert(cardType, card); @@ -584,7 +585,7 @@ bool DeckLoader::convertToCockatriceFormat(QString fileName) QString DeckLoader::getCardZoneFromName(QString cardName, QString currentZoneName) { - CardInfoPtr card = CardDatabaseManager::getInstance()->getCardInfo(cardName); + CardInfoPtr card = CardDatabaseManager::query()->getCardInfo(cardName); if (card && card->getIsToken()) { return DECK_ZONE_TOKENS; @@ -596,7 +597,7 @@ QString DeckLoader::getCardZoneFromName(QString cardName, QString currentZoneNam QString DeckLoader::getCompleteCardName(const QString &cardName) const { if (CardDatabaseManager::getInstance()) { - ExactCard temp = CardDatabaseManager::getInstance()->guessCard({cardName}); + ExactCard temp = CardDatabaseManager::query()->guessCard({cardName}); if (temp) { return temp.getName(); } diff --git a/cockatrice/src/deck/deck_stats_interface.cpp b/cockatrice/src/deck/deck_stats_interface.cpp index 389ec9a68..96865d9e7 100644 --- a/cockatrice/src/deck/deck_stats_interface.cpp +++ b/cockatrice/src/deck/deck_stats_interface.cpp @@ -71,7 +71,7 @@ void DeckStatsInterface::analyzeDeck(DeckList *deck) void DeckStatsInterface::copyDeckWithoutTokens(DeckList &source, DeckList &destination) { auto copyIfNotAToken = [this, &destination](const auto node, const auto card) { - CardInfoPtr dbCard = cardDatabase.getCardInfo(card->getName()); + CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName()); if (dbCard && !dbCard->getIsToken()) { DecklistCardNode *addedCard = destination.addCard(card->getName(), node->getName(), -1); addedCard->setNumber(card->getNumber()); diff --git a/cockatrice/src/dialogs/dlg_edit_tokens.cpp b/cockatrice/src/dialogs/dlg_edit_tokens.cpp index 8ad0fdbbc..56711dda6 100644 --- a/cockatrice/src/dialogs/dlg_edit_tokens.cpp +++ b/cockatrice/src/dialogs/dlg_edit_tokens.cpp @@ -153,7 +153,7 @@ void DlgEditTokens::actAddToken() name = getTextWithMax(this, tr("Add token"), tr("Please enter the name of the token:")); if (name.isEmpty()) return; - if (databaseModel->getDatabase()->getCardInfo(name)) { + if (databaseModel->getDatabase()->query()->getCardInfo(name)) { QMessageBox::critical(this, tr("Error"), tr("The chosen name conflicts with an existing card or token.\nMake sure to enable " "the 'Token' set in the \"Manage sets\" dialog to display them correctly.")); diff --git a/cockatrice/src/dialogs/dlg_select_set_for_cards.cpp b/cockatrice/src/dialogs/dlg_select_set_for_cards.cpp index ac23e4159..9f20067b2 100644 --- a/cockatrice/src/dialogs/dlg_select_set_for_cards.cpp +++ b/cockatrice/src/dialogs/dlg_select_set_for_cards.cpp @@ -152,8 +152,8 @@ void DlgSelectSetForCards::actOK() continue; } model->removeRow(find_card.row(), find_card.parent()); - CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(card); - PrintingInfo printing = CardDatabaseManager::getInstance()->getSpecificPrinting(card, modifiedSet, ""); + CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(card); + PrintingInfo printing = CardDatabaseManager::query()->getSpecificPrinting(card, modifiedSet, ""); model->addCard(ExactCard(cardInfo, printing), DECK_ZONE_MAIN); } } @@ -223,7 +223,7 @@ QMap DlgSelectSetForCards::getSetsForCards() if (!currentCard) continue; - CardInfoPtr infoPtr = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName()); + CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); if (!infoPtr) continue; @@ -291,13 +291,14 @@ void DlgSelectSetForCards::updateCardLists() if (!found) { // The card was not in any selected set - ExactCard card = CardDatabaseManager::getInstance()->getCard({currentCard->getName()}); + ExactCard card = CardDatabaseManager::query()->getCard({currentCard->getName()}); CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(uneditedCardsFlowWidget); picture_widget->setCard(card); uneditedCardsFlowWidget->addWidget(picture_widget); } else { - ExactCard card = CardDatabaseManager::getInstance()->getCard( + ExactCard card = CardDatabaseManager::query()->getCard( {currentCard->getName(), CardDatabaseManager::getInstance() + ->query() ->getSpecificPrinting(currentCard->getName(), foundSetName, "") .getUuid()}); CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(modifiedCardsFlowWidget); @@ -377,7 +378,7 @@ QMap DlgSelectSetForCards::getCardsForSets() if (!currentCard) continue; - CardInfoPtr infoPtr = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName()); + CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); if (!infoPtr) continue; @@ -627,17 +628,15 @@ void SetEntryWidget::updateCardDisplayWidgets() for (const QString &cardName : possibleCards) { CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(cardListContainer); - QString providerId = - CardDatabaseManager::getInstance()->getSpecificPrinting(cardName, setName, nullptr).getUuid(); - picture_widget->setCard(CardDatabaseManager::getInstance()->getCard({cardName, providerId})); + QString providerId = CardDatabaseManager::query()->getSpecificPrinting(cardName, setName, nullptr).getUuid(); + picture_widget->setCard(CardDatabaseManager::query()->getCard({cardName, providerId})); cardListContainer->addWidget(picture_widget); } for (const QString &cardName : unusedCards) { CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(alreadySelectedCardListContainer); - QString providerId = - CardDatabaseManager::getInstance()->getSpecificPrinting(cardName, setName, nullptr).getUuid(); - picture_widget->setCard(CardDatabaseManager::getInstance()->getCard({cardName, providerId})); + QString providerId = CardDatabaseManager::query()->getSpecificPrinting(cardName, setName, nullptr).getUuid(); + picture_widget->setCard(CardDatabaseManager::query()->getCard({cardName, providerId})); alreadySelectedCardListContainer->addWidget(picture_widget); } } diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp index 42c7e2cbc..f107884c3 100644 --- a/cockatrice/src/filters/deck_filter_string.cpp +++ b/cockatrice/src/filters/deck_filter_string.cpp @@ -118,7 +118,7 @@ static void setupParserRules() return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool { int count = 0; deck->deckLoader->forEachCard([&](InnerDecklistNode *, const DecklistCardNode *node) { - auto cardInfoPtr = CardDatabaseManager::getInstance()->getCardInfo(node->getName()); + auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName()); if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) { count += node->getNumber(); } diff --git a/cockatrice/src/game/board/abstract_card_item.cpp b/cockatrice/src/game/board/abstract_card_item.cpp index 7fdc25ffe..ea23f39c0 100644 --- a/cockatrice/src/game/board/abstract_card_item.cpp +++ b/cockatrice/src/game/board/abstract_card_item.cpp @@ -57,7 +57,7 @@ void AbstractCardItem::pixmapUpdated() void AbstractCardItem::refreshCardInfo() { - exactCard = CardDatabaseManager::getInstance()->getCard(cardRef); + exactCard = CardDatabaseManager::query()->getCard(cardRef); if (!exactCard && !cardRef.name.isEmpty()) { auto info = CardInfo::newInstance(cardRef.name, "", true, {}, {}, {}, {}, false, false, -1, false); diff --git a/cockatrice/src/game/deckview/deck_view_container.cpp b/cockatrice/src/game/deckview/deck_view_container.cpp index 2f6e9a105..7dd2da41b 100644 --- a/cockatrice/src/game/deckview/deck_view_container.cpp +++ b/cockatrice/src/game/deckview/deck_view_container.cpp @@ -332,7 +332,7 @@ void DeckViewContainer::deckSelectFinished(const Response &r) { const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); DeckLoader newDeck(QString::fromStdString(resp.deck())); - PictureLoader::cacheCardPixmaps(CardDatabaseManager::getInstance()->getCards(newDeck.getCardRefList())); + PictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(newDeck.getCardRefList())); setDeck(newDeck); switchToDeckLoadedView(); } diff --git a/cockatrice/src/game/dialogs/dlg_create_token.cpp b/cockatrice/src/game/dialogs/dlg_create_token.cpp index 101727bee..8da2bc722 100644 --- a/cockatrice/src/game/dialogs/dlg_create_token.cpp +++ b/cockatrice/src/game/dialogs/dlg_create_token.cpp @@ -205,9 +205,9 @@ void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QMo CardRef ref; ref.name = cardInfo->getName(); ref.providerId = cardProviderId; - pic->setCard(CardDatabaseManager::getInstance()->getCard(ref)); + pic->setCard(CardDatabaseManager::query()->getCard(ref)); } else { - pic->setCard(CardDatabaseManager::getInstance()->getPreferredCard(cardInfo)); + pic->setCard(CardDatabaseManager::query()->getPreferredCard(cardInfo)); } } diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp index 114655cb8..2a669b32d 100644 --- a/cockatrice/src/game/player/menu/card_menu.cpp +++ b/cockatrice/src/game/player/menu/card_menu.cpp @@ -322,7 +322,7 @@ void CardMenu::addRelatedCardView() bool atLeastOneGoodRelationFound = false; QList relatedCards = exactCard.getInfo().getAllRelatedCards(); for (const CardRelation *cardRelation : relatedCards) { - CardInfoPtr relatedCard = CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()); + CardInfoPtr relatedCard = CardDatabaseManager::query()->getCardInfo(cardRelation->getName()); if (relatedCard != nullptr) { atLeastOneGoodRelationFound = true; break; @@ -366,10 +366,10 @@ void CardMenu::addRelatedCardActions() int index = 0; QAction *createRelatedCards = nullptr; for (const CardRelation *cardRelation : relatedCards) { - ExactCard relatedCard = CardDatabaseManager::getInstance()->getCardFromSameSet(cardRelation->getName(), - card->getCard().getPrinting()); + ExactCard relatedCard = + CardDatabaseManager::query()->getCardFromSameSet(cardRelation->getName(), card->getCard().getPrinting()); if (!relatedCard) { - relatedCard = CardDatabaseManager::getInstance()->getCard({cardRelation->getName()}); + relatedCard = CardDatabaseManager::query()->getCard({cardRelation->getName()}); } if (!relatedCard) { continue; diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index e7b50dac0..b466009ea 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -840,8 +840,7 @@ void PlayerActions::actCreateToken() lastTokenInfo = dlg.getTokenInfo(); - ExactCard correctedCard = - CardDatabaseManager::getInstance()->guessCard({lastTokenInfo.name, lastTokenInfo.providerId}); + ExactCard correctedCard = CardDatabaseManager::query()->guessCard({lastTokenInfo.name, lastTokenInfo.providerId}); if (correctedCard) { lastTokenInfo.name = correctedCard.getName(); lastTokenTableRow = TableZone::clampValidTableRow(2 - correctedCard.getInfo().getTableRow()); @@ -903,7 +902,7 @@ void PlayerActions::setLastToken(CardInfoPtr cardInfo) void PlayerActions::actCreatePredefinedToken() { auto *action = static_cast(sender()); - CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(action->text()); + CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(action->text()); if (!cardInfo) { return; } @@ -929,8 +928,8 @@ void PlayerActions::actCreateRelatedCard() * then let's allow it to be created via "create another token" */ if (createRelatedFromRelation(sourceCard, cardRelation) && cardRelation->getCanCreateAnother()) { - ExactCard relatedCard = CardDatabaseManager::getInstance()->getCardFromSameSet( - cardRelation->getName(), sourceCard->getCard().getPrinting()); + ExactCard relatedCard = CardDatabaseManager::query()->getCardFromSameSet(cardRelation->getName(), + sourceCard->getCard().getPrinting()); setLastToken(relatedCard.getCardPtr()); } } @@ -1010,7 +1009,7 @@ void PlayerActions::actCreateAllRelatedCards() * then assign the first to the "Create another" shortcut. */ if (cardRelation != nullptr && cardRelation->getCanCreateAnother()) { - CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()); + CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(cardRelation->getName()); setLastToken(cardInfo); } } @@ -1057,7 +1056,7 @@ void PlayerActions::createCard(const CardItem *sourceCard, CardRelation::AttachType attachType, bool persistent) { - CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(dbCardName); + CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(dbCardName); if (cardInfo == nullptr || sourceCard == nullptr) { return; @@ -1093,8 +1092,8 @@ void PlayerActions::createCard(const CardItem *sourceCard, cmd.set_x(gridPoint.x()); cmd.set_y(gridPoint.y()); - ExactCard relatedCard = CardDatabaseManager::getInstance()->getCardFromSameSet(cardInfo->getName(), - sourceCard->getCard().getPrinting()); + ExactCard relatedCard = + CardDatabaseManager::query()->getCardFromSameSet(cardInfo->getName(), sourceCard->getCard().getPrinting()); switch (attachType) { case CardRelation::DoesNotAttach: diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp index 260d23102..dcd4cc9aa 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp @@ -55,7 +55,7 @@ QWidget *CardGroupDisplayWidget::constructWidgetForIndex(QPersistentModelIndex i auto widget = new CardInfoPictureWithTextOverlayWidget(getLayoutParent(), true); widget->setScaleFactor(cardSizeWidget->getSlider()->value()); - widget->setCard(CardDatabaseManager::getInstance()->getCard({cardName, cardProviderId})); + widget->setCard(CardDatabaseManager::query()->getCard({cardName, cardProviderId})); connect(widget, &CardInfoPictureWithTextOverlayWidget::imageClicked, this, &CardGroupDisplayWidget::onClick); connect(widget, &CardInfoPictureWithTextOverlayWidget::hoveredOnCard, this, &CardGroupDisplayWidget::onHover); diff --git a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp index cf0626dd1..d11590a05 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp @@ -57,7 +57,7 @@ void CardInfoDisplayWidget::setCard(const ExactCard &card) void CardInfoDisplayWidget::setCard(const CardRef &cardRef) { - setCard(CardDatabaseManager::getInstance()->guessCard(cardRef)); + setCard(CardDatabaseManager::query()->guessCard(cardRef)); if (exactCard.isEmpty()) { text->setInvalidCardName(cardRef.name); } diff --git a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp index 44b56a9af..6168fe903 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp @@ -160,12 +160,12 @@ void CardInfoFrameWidget::setCard(const ExactCard &card) void CardInfoFrameWidget::setCard(const QString &cardName) { - setCard(CardDatabaseManager::getInstance()->guessCard({cardName})); + setCard(CardDatabaseManager::query()->guessCard({cardName})); } void CardInfoFrameWidget::setCard(const CardRef &cardRef) { - setCard(CardDatabaseManager::getInstance()->getCard(cardRef)); + setCard(CardDatabaseManager::query()->getCard(cardRef)); } void CardInfoFrameWidget::setCard(AbstractCardItem *card) diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp index 7ca14d490..2375bc483 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp @@ -368,7 +368,7 @@ QMenu *CardInfoPictureWidget::createViewRelatedCardsMenu() QList relatedCards = exactCard.getInfo().getAllRelatedCards(); auto relatedCardExists = [](const CardRelation *cardRelation) { - return CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()) != nullptr; + return CardDatabaseManager::query()->getCardInfo(cardRelation->getName()) != nullptr; }; bool atLeastOneGoodRelationFound = std::any_of(relatedCards.begin(), relatedCards.end(), relatedCardExists); @@ -383,7 +383,7 @@ QMenu *CardInfoPictureWidget::createViewRelatedCardsMenu() QAction *viewCard = viewRelatedCards->addAction(relatedCardName); connect(viewCard, &QAction::triggered, this, [this, &relatedCardName] { emit cardChanged( - CardDatabaseManager::getInstance()->getCard({relatedCardName, exactCard.getPrinting().getUuid()})); + CardDatabaseManager::query()->getCard({relatedCardName, exactCard.getPrinting().getUuid()})); }); viewRelatedCards->addAction(viewCard); } diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp index b2030612c..11d87be40 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_base_widget.cpp @@ -87,7 +87,7 @@ QHash ManaBaseWidget::analyzeManaBase() continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName()); + CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); if (info) { auto devotion = determineManaProduction(info->getText()); mergeManaCounts(manaBaseMap, devotion); diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp index 430e95f81..5a4e14dc9 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_curve_widget.cpp @@ -53,7 +53,7 @@ std::unordered_map ManaCurveWidget::analyzeManaCurve() continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName()); + CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); if (info) { int cmc = info->getCmc().toInt(); manaCurveMap[cmc]++; diff --git a/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp index d26e11763..4960b009a 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/mana_devotion_widget.cpp @@ -55,7 +55,7 @@ std::unordered_map ManaDevotionWidget::analyzeManaDevotion() continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName()); + CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName()); if (info) { auto devotion = countManaSymbols(info->getManaCost()); mergeManaCounts(manaDevotionMap, devotion); diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp index 5e4cb4949..bee131f00 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp @@ -182,11 +182,11 @@ ExactCard DeckEditorDatabaseDisplayWidget::getCardOrPinnedPrinting(QString cardN { const auto &cardProviderId = SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardName); - ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName}); + ExactCard card = CardDatabaseManager::query()->getCard({cardName}); if (cardProviderId != "") { return ExactCard(card.getCardPtr(), - CardDatabaseManager::getInstance()->getSpecificPrinting({cardName, cardProviderId})); + CardDatabaseManager::query()->getSpecificPrinting({cardName, cardProviderId})); } return card; diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp index bafe393a1..dc995ff17 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp @@ -227,7 +227,7 @@ ExactCard DeckEditorDeckDockWidget::getCurrentCard() if (!current.model()->hasChildren(current.sibling(current.row(), 0))) { QString cardName = current.sibling(current.row(), 1).data().toString(); QString providerId = current.sibling(current.row(), 4).data().toString(); - if (ExactCard selectedCard = CardDatabaseManager::getInstance()->getCard({cardName, providerId})) { + if (ExactCard selectedCard = CardDatabaseManager::query()->getCard({cardName, providerId})) { return selectedCard; } } @@ -286,7 +286,7 @@ void DeckEditorDeckDockWidget::updateBannerCardComboBox() continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - if (CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef())) { + if (CardDatabaseManager::query()->getCard(currentCard->toCardRef())) { bannerCardSet.insert({currentCard->getName(), currentCard->getCardProviderId()}); } } @@ -486,7 +486,7 @@ bool DeckEditorDeckDockWidget::swapCard(const QModelIndex ¤tIndex) offsetCountAtIndex(currentIndex, -1); const QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN; - ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName, cardProviderID}); + ExactCard card = CardDatabaseManager::query()->getCard({cardName, cardProviderID}); QModelIndex newCardIndex = card ? deckModel->addCard(card, otherZoneName) // Third argument (true) says create the card no matter what, even if not in DB : deckModel->addPreferredPrintingCard(cardName, otherZoneName, true); diff --git a/cockatrice/src/interface/widgets/general/home_widget.cpp b/cockatrice/src/interface/widgets/general/home_widget.cpp index cdf510abe..50823db4b 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.cpp +++ b/cockatrice/src/interface/widgets/general/home_widget.cpp @@ -89,7 +89,7 @@ void HomeWidget::updateRandomCard() break; case BackgroundSources::RandomCardArt: do { - newCard = CardDatabaseManager::getInstance()->getRandomCard(); + newCard = CardDatabaseManager::query()->getRandomCard(); } while (newCard == backgroundSourceCard->getCard() && newCard.getCardPtr()->getProperty("layout") != "normal"); break; @@ -99,17 +99,17 @@ void HomeWidget::updateRandomCard() if (!cardRefs.empty()) { if (cardRefs.size() == 1) { - newCard = CardDatabaseManager::getInstance()->getCard(cardRefs.first()); + newCard = CardDatabaseManager::query()->getCard(cardRefs.first()); } else { // Keep picking until different do { int idx = QRandomGenerator::global()->bounded(cardRefs.size()); - newCard = CardDatabaseManager::getInstance()->getCard(cardRefs.at(idx)); + newCard = CardDatabaseManager::query()->getCard(cardRefs.at(idx)); } while (newCard == oldCard); } } else { do { - newCard = CardDatabaseManager::getInstance()->getRandomCard(); + newCard = CardDatabaseManager::query()->getRandomCard(); } while (newCard == oldCard); } break; diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp index 8e599ceb1..9ed59d46e 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp @@ -196,7 +196,7 @@ void PrintingSelectorCardOverlayWidget::customMenu(QPoint point) const QString &relatedCardName = rel->getName(); QAction *relatedCard = relatedMenu->addAction(relatedCardName); connect(relatedCard, &QAction::triggered, deckEditor, [this, relatedCardName] { - deckEditor->updateCard(CardDatabaseManager::getInstance()->getCard({relatedCardName})); + deckEditor->updateCard(CardDatabaseManager::query()->getCard({relatedCardName})); deckEditor->showPrintingSelector(); }); } diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp index 4ff2f8f1f..1fddc9724 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp @@ -12,7 +12,7 @@ VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWi FilterTreeModel *_filterModel) : QWidget(parent), filterModel(_filterModel) { - allMainCardTypesWithCount = CardDatabaseManager::getInstance()->getAllMainCardTypesWithCount(); + allMainCardTypesWithCount = CardDatabaseManager::query()->getAllMainCardTypesWithCount(); // Get all main card types with their count setMaximumHeight(75); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp index 6cc128a0d..9c531ba1a 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp @@ -13,7 +13,7 @@ VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidg FilterTreeModel *_filterModel) : QWidget(parent), filterModel(_filterModel) { - allSubCardTypesWithCount = CardDatabaseManager::getInstance()->getAllSubCardTypesWithCount(); + allSubCardTypesWithCount = CardDatabaseManager::query()->getAllSubCardTypesWithCount(); setMinimumWidth(300); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index de8d9f05b..95a463b23 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -303,7 +303,7 @@ void VisualDatabaseDisplayWidget::loadPage(int start, int end) QVariant name = databaseDisplayModel->data(index, Qt::DisplayRole); qCDebug(VisualDatabaseDisplayLog) << name.toString(); - if (CardInfoPtr info = CardDatabaseManager::getInstance()->getCardInfo(name.toString())) { + if (CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(name.toString())) { if (!setFilters.empty()) { SetToPrintingsMap setMap = info->getSets(); for (const CardFilter *setFilter : setFilters) { @@ -314,7 +314,7 @@ void VisualDatabaseDisplayWidget::loadPage(int start, int end) } } } else { - addCard(CardDatabaseManager::getInstance()->getPreferredCard(info)); + addCard(CardDatabaseManager::query()->getPreferredCard(info)); } } else { qCDebug(VisualDatabaseDisplayLog) << "Card not found in database!"; diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp index a6f0734d3..0f3fc9e49 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp @@ -101,7 +101,7 @@ QList VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGe continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); + ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef()); if (card) { mainDeckCards.append(card); } diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp index 369e09be2..6a23d8215 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp @@ -42,7 +42,7 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_ if (!searchBar->hasFocus()) return; - ExactCard card = CardDatabaseManager::getInstance()->getCard({searchBar->text()}); + ExactCard card = CardDatabaseManager::query()->getCard({searchBar->text()}); if (card) { emit cardAdditionRequested(card); } @@ -103,7 +103,7 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_ // Search button functionality searchPushButton = new QPushButton(this); connect(searchPushButton, &QPushButton::clicked, this, [=, this]() { - ExactCard card = CardDatabaseManager::getInstance()->getCard({searchBar->text()}); + ExactCard card = CardDatabaseManager::query()->getCard({searchBar->text()}); if (card) { emit cardAdditionRequested(card); } diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp index 3cdd2a72c..695918861 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp @@ -76,7 +76,7 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess) } auto bannerCard = deckLoader->getBannerCard().name.isEmpty() ? ExactCard() - : CardDatabaseManager::getInstance()->getCard(deckLoader->getBannerCard()); + : CardDatabaseManager::query()->getCard(deckLoader->getBannerCard()); bannerCardDisplayWidget->setCard(bannerCard); bannerCardDisplayWidget->setFontSize(24); @@ -160,7 +160,7 @@ QString DeckPreviewWidget::getColorIdentity() QSet colorSet; // A set to collect unique color symbols (e.g., W, U, B, R, G) for (const QString &cardName : cardList) { - CardInfoPtr currentCard = CardDatabaseManager::getInstance()->getCardInfo(cardName); + CardInfoPtr currentCard = CardDatabaseManager::query()->getCardInfo(cardName); if (currentCard) { QString colors = currentCard->getColors(); // Assuming this returns something like "WUB" for (const QChar &color : colors) { @@ -293,7 +293,7 @@ void DeckPreviewWidget::setBannerCard(int /* changedIndex */) CardRef cardRef = {name, id}; deckLoader->setBannerCard(cardRef); deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath)); - bannerCardDisplayWidget->setCard(CardDatabaseManager::getInstance()->getCard(cardRef)); + bannerCardDisplayWidget->setCard(CardDatabaseManager::query()->getCard(cardRef)); } void DeckPreviewWidget::imageClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance) diff --git a/cockatrice/src/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/tabs/abstract_tab_deck_editor.cpp index 455b5ca29..fdead20c3 100644 --- a/cockatrice/src/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/tabs/abstract_tab_deck_editor.cpp @@ -161,7 +161,7 @@ void AbstractTabDeckEditor::openDeck(DeckLoader *deck) void AbstractTabDeckEditor::setDeck(DeckLoader *_deck) { deckDockWidget->setDeck(_deck); - PictureLoader::cacheCardPixmaps(CardDatabaseManager::getInstance()->getCards(getDeckList()->getCardRefList())); + PictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(getDeckList()->getCardRefList())); setModified(false); // If they load a deck, make the deck list appear diff --git a/cockatrice/src/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp b/cockatrice/src/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp index 71bf088eb..cde18053b 100644 --- a/cockatrice/src/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp +++ b/cockatrice/src/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp @@ -12,7 +12,7 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi setLayout(layout); cardPictureWidget = new CardInfoPictureWidget(this); - cardPictureWidget->setCard(CardDatabaseManager::getInstance()->guessCard({toDisplay.sanitized})); + cardPictureWidget->setCard(CardDatabaseManager::query()->guessCard({toDisplay.sanitized})); nameLabel = new QLabel(this); nameLabel->setText(toDisplay.name); diff --git a/cockatrice/src/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp b/cockatrice/src/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp index cff480dfe..bf7444b5e 100644 --- a/cockatrice/src/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp +++ b/cockatrice/src/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp @@ -15,7 +15,7 @@ EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCom setLayout(layout); commanderPicture = new CardInfoPictureWidget(this); - commanderPicture->setCard(CardDatabaseManager::getInstance()->getCard({commanderDetails.getName()})); + commanderPicture->setCard(CardDatabaseManager::query()->getCard({commanderDetails.getName()})); QWidget *currentParent = parentWidget(); TabEdhRecMain *parentTab = nullptr; diff --git a/cockatrice/src/tabs/api/edhrec/tab_edhrec_main.cpp b/cockatrice/src/tabs/api/edhrec/tab_edhrec_main.cpp index 4a0afc099..36089886a 100644 --- a/cockatrice/src/tabs/api/edhrec/tab_edhrec_main.cpp +++ b/cockatrice/src/tabs/api/edhrec/tab_edhrec_main.cpp @@ -136,7 +136,7 @@ void TabEdhRecMain::retranslateUi() void TabEdhRecMain::doSearch() { - CardInfoPtr searchedCard = CardDatabaseManager::getInstance()->getCardInfo(searchBar->text()); + CardInfoPtr searchedCard = CardDatabaseManager::query()->getCardInfo(searchBar->text()); if (!searchedCard) { return; } diff --git a/cockatrice/src/tabs/tab_game.cpp b/cockatrice/src/tabs/tab_game.cpp index eca470be3..52d295b53 100644 --- a/cockatrice/src/tabs/tab_game.cpp +++ b/cockatrice/src/tabs/tab_game.cpp @@ -740,7 +740,7 @@ void TabGame::loadDeckForLocalPlayer(Player *localPlayer, int playerId, ServerIn TabbedDeckViewContainer *deckViewContainer = deckViewContainers.value(playerId); if (playerInfo.has_deck_list()) { DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list())); - PictureLoader::cacheCardPixmaps(CardDatabaseManager::getInstance()->getCards(newDeck.getCardRefList())); + PictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(newDeck.getCardRefList())); deckViewContainer->playerDeckView->setDeck(newDeck); localPlayer->setDeck(newDeck); } diff --git a/cockatrice/src/utility/deck_list_sort_filter_proxy_model.cpp b/cockatrice/src/utility/deck_list_sort_filter_proxy_model.cpp index 65d7d17e7..a7776cbec 100644 --- a/cockatrice/src/utility/deck_list_sort_filter_proxy_model.cpp +++ b/cockatrice/src/utility/deck_list_sort_filter_proxy_model.cpp @@ -20,8 +20,8 @@ bool DeckListSortFilterProxyModel::lessThan(const QModelIndex &left, const QMode auto *lNode = static_cast(left.internalPointer()); auto *rNode = static_cast(right.internalPointer()); - CardInfoPtr lInfo = CardDatabaseManager::getInstance()->guessCard({lNode->getName()}).getCardPtr(); - CardInfoPtr rInfo = CardDatabaseManager::getInstance()->guessCard({rNode->getName()}).getCardPtr(); + CardInfoPtr lInfo = CardDatabaseManager::query()->guessCard({lNode->getName()}).getCardPtr(); + CardInfoPtr rInfo = CardDatabaseManager::query()->guessCard({rNode->getName()}).getCardPtr(); // Example: multiple tie-break criteria (colors > cmc > name) for (const QString &crit : sortCriteria) { diff --git a/dbconverter/CMakeLists.txt b/dbconverter/CMakeLists.txt index 20bb5c825..bc03a5ad3 100644 --- a/dbconverter/CMakeLists.txt +++ b/dbconverter/CMakeLists.txt @@ -8,6 +8,8 @@ set(dbconverter_SOURCES ../cockatrice/src/card/card_info.cpp ../cockatrice/src/card/exact_card.cpp ../cockatrice/src/database/card_database.cpp + ../cockatrice/src/database/card_database_loader.cpp + ../cockatrice/src/database/card_database_querier.cpp ../cockatrice/src/database/parser/card_database_parser.cpp ../cockatrice/src/database/parser/cockatrice_xml_3.cpp ../cockatrice/src/database/parser/cockatrice_xml_4.cpp diff --git a/dbconverter/src/main.h b/dbconverter/src/main.h index 3e384c14a..ccde6b20e 100644 --- a/dbconverter/src/main.h +++ b/dbconverter/src/main.h @@ -9,7 +9,7 @@ class CardDatabaseConverter : public CardDatabase public: LoadStatus loadCardDatabase(const QString &path) { - return CardDatabase::loadCardDatabase(path); + return loader->loadCardDatabase(path); } bool saveCardDatabase(const QString &fileName) diff --git a/tests/carddatabase/CMakeLists.txt b/tests/carddatabase/CMakeLists.txt index 590c2daeb..9797d27cf 100644 --- a/tests/carddatabase/CMakeLists.txt +++ b/tests/carddatabase/CMakeLists.txt @@ -21,6 +21,8 @@ add_executable( ../../cockatrice/src/card/card_info.cpp ../../cockatrice/src/card/exact_card.cpp ../../cockatrice/src/database/card_database.cpp + ../../cockatrice/src/database/card_database_loader.cpp + ../../cockatrice/src/database/card_database_querier.cpp ../../cockatrice/src/database/parser/card_database_parser.cpp ../../cockatrice/src/database/parser/cockatrice_xml_3.cpp ../../cockatrice/src/database/parser/cockatrice_xml_4.cpp @@ -35,6 +37,8 @@ add_executable( ../../cockatrice/src/card/card_info.cpp ../../cockatrice/src/card/exact_card.cpp ../../cockatrice/src/database/card_database.cpp + ../../cockatrice/src/database/card_database_loader.cpp + ../../cockatrice/src/database/card_database_querier.cpp ../../cockatrice/src/database/card_database_manager.cpp ../../cockatrice/src/database/parser/card_database_parser.cpp ../../cockatrice/src/database/parser/cockatrice_xml_3.cpp diff --git a/tests/carddatabase/carddatabase_test.cpp b/tests/carddatabase/carddatabase_test.cpp index c572dcf3b..f3de287e5 100644 --- a/tests/carddatabase/carddatabase_test.cpp +++ b/tests/carddatabase/carddatabase_test.cpp @@ -13,21 +13,21 @@ TEST(CardDatabaseTest, LoadXml) // ensure the card database is empty at start ASSERT_EQ(0, db->getCardList().size()) << "Cards not empty at start"; ASSERT_EQ(0, db->getSetList().size()) << "Sets not empty at start"; - ASSERT_EQ(0, db->getAllMainCardTypes().size()) << "Types not empty at start"; + ASSERT_EQ(0, db->query()->getAllMainCardTypes().size()) << "Types not empty at start"; ASSERT_EQ(NotLoaded, db->getLoadStatus()) << "Incorrect status at start"; // load dummy cards and test result db->loadCardDatabases(); ASSERT_EQ(9, db->getCardList().size()) << "Wrong card count after load"; ASSERT_EQ(5, db->getSetList().size()) << "Wrong sets count after load"; - ASSERT_EQ(3, db->getAllMainCardTypes().size()) << "Wrong types count after load"; + ASSERT_EQ(3, db->query()->getAllMainCardTypes().size()) << "Wrong types count after load"; ASSERT_EQ(Ok, db->getLoadStatus()) << "Wrong status after load"; // ensure the card database is empty after clear() db->clear(); ASSERT_EQ(0, db->getCardList().size()) << "Cards not empty after clear"; ASSERT_EQ(0, db->getSetList().size()) << "Sets not empty after clear"; - ASSERT_EQ(0, db->getAllMainCardTypes().size()) << "Types not empty after clear"; + ASSERT_EQ(0, db->query()->getAllMainCardTypes().size()) << "Types not empty after clear"; ASSERT_EQ(NotLoaded, db->getLoadStatus()) << "Incorrect status after clear"; } } // namespace diff --git a/tests/carddatabase/filter_string_test.cpp b/tests/carddatabase/filter_string_test.cpp index 6485a9ebd..3055bb76a 100644 --- a/tests/carddatabase/filter_string_test.cpp +++ b/tests/carddatabase/filter_string_test.cpp @@ -18,10 +18,10 @@ class CardQuery : public ::testing::Test protected: void SetUp() override { - cat = CardDatabaseManager::getInstance()->getCardBySimpleName("Cat"); - notDeadAfterAll = CardDatabaseManager::getInstance()->getCardBySimpleName("Not Dead"); - truth = CardDatabaseManager::getInstance()->getCardBySimpleName("Truth"); - doctor = CardDatabaseManager::getInstance()->getCardBySimpleName("Doctor"); + cat = CardDatabaseManager::query()->getCardBySimpleName("Cat"); + notDeadAfterAll = CardDatabaseManager::query()->getCardBySimpleName("Not Dead"); + truth = CardDatabaseManager::query()->getCardBySimpleName("Truth"); + doctor = CardDatabaseManager::query()->getCardBySimpleName("Doctor"); } // void TearDown() override {}