mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-09 11:33:25 -08:00
* [Card] Import Scryfall Tagger tags from MTGJson * [Card] Search cards by Scryfall Tagger tag * [Card] Add a Tag attribute to the card filter tree * [Card] Add a Tags filter to the visual card database * [Oracle] Add a script to inject Scryfall tags into AllPrintings * [Card] Elide long tag lists in the card info and drop the Scryfall label from the tag filter tooltip * [Oracle] Load card tags from a tag database during import Add a TagDatabase loader that understands Scryfall's Oracle Tags bulk data and user-supplied tag files (tag objects, flat oracle-id or name maps, optional manifest, JSON or JSONL, gzip/xz/zip). The importer joins the slugs on identifiers.scryfallOracleId while the identifiers are still available, falls back to the card name, and unions them with any tags the source already provides. Split-card faces merge through the existing tag union path. This replaces oracle/scripts/inject_scryfall_tags.py, which patched AllPrintings.json before import. Loading during import keeps tags on by default for every source and lets users pair Oracle with any tag database. * [Oracle] Add a tag data step to the import wizard Insert a Tags page between set selection and the import. It downloads Scryfall's Oracle Tags by default (or a user-supplied file/URL), can include parent tags, and persists tagsenabled, tagssource and tagsparents in oracle.ini. The page loads asynchronously and soft-fails in background mode, so a tag download or parse error never aborts the card database import. * [Help] Describe tag search without naming Scryfall Tags can come from Scryfall's Oracle Tags or any user-supplied tag database, so the search help should not claim a single source. * [Oracle] Fix Scryfall tag requests and the retry loop api.scryfall.com rejects requests that lack an Accept header with HTTP 400, and QNetworkAccessManager does not add one. Send application/json for the bulk metadata request and */* for the tag file, and surface the URL plus Scryfall's JSON error body when a request fails. A failed tag load used to call next(), which re-ran validatePage() and started the same failing download again, trapping the user in an error loop. Stay on the page instead, drop the unusable database, and tell the user they can retry, change the source, or untick the option to import without tags. Also explain parent tags inline with a real Scryfall hierarchy example. * [Oracle] Give the parent-tag explainer room to breathe The wrapped explainer sat flush under the checkbox with no separation from the status label, which made the paragraph look cramped. Indent it under the checkbox and add a little vertical margin. * [Oracle] Stop the parent-tag explainer from being clipped A word-wrapped QLabel reports a one-line sizeHint, so the wizard page reserved too little height and the explanation lost its top and bottom lines. Pin the vertical size policy to Minimum on the explainer and on the status label, so the wrapped height becomes part of the page minimum. Verified with a layout probe: the label went from 28 px tall (needed 56) to its full height. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
252 lines
9 KiB
C++
252 lines
9 KiB
C++
#ifndef COCKATRICE_CARD_DATABASE_QUERIER_H
|
|
#define COCKATRICE_CARD_DATABASE_QUERIER_H
|
|
|
|
#include "../card_info.h"
|
|
#include "../printing/exact_card.h"
|
|
#include "libcockatrice/card/printing/printing_info.h"
|
|
|
|
#include <QList>
|
|
#include <QMap>
|
|
#include <QObject>
|
|
#include <QString>
|
|
#include <QStringList>
|
|
#include <qtmetamacros.h>
|
|
|
|
class CardDatabase;
|
|
class ICardPreferenceProvider;
|
|
struct CardRef;
|
|
|
|
/**
|
|
* @class CardDatabaseQuerier
|
|
* @ingroup CardDatabase
|
|
* @brief Provides lookup and convenience functions for querying cards and their printings.
|
|
*
|
|
* The CardDatabaseQuerier class offers various lookup helpers for retrieving card information
|
|
* (e.g., CardInfoPtr, ExactCard, and PrintingInfo) from a CardDatabase. It also applies user
|
|
* printing preferences via ICardPreferenceProvider when determining preferred printings.
|
|
*/
|
|
class CardDatabaseQuerier : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
/**
|
|
* @brief Constructs a CardDatabaseQuerier.
|
|
*
|
|
* @param parent Parent QObject.
|
|
* @param db Pointer to the CardDatabase used for lookups.
|
|
* @param prefs Pointer to card preference provider which supplies user-preference for printings.
|
|
*/
|
|
explicit CardDatabaseQuerier(QObject *parent, const CardDatabase *db, const ICardPreferenceProvider *prefs);
|
|
|
|
/**
|
|
* @brief Retrieves a card by its exact name.
|
|
*
|
|
* @param cardName Exact card name.
|
|
* @return A CardInfoPtr, or null if no matching card exists.
|
|
*/
|
|
[[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const;
|
|
|
|
/**
|
|
* @brief Retrieves multiple cards by their exact names.
|
|
*
|
|
* Failed lookups are skipped and not included in the result.
|
|
*
|
|
* @param cardNames List of exact card names.
|
|
* @return List of CardInfoPtr objects for which a match was found.
|
|
*/
|
|
[[nodiscard]] QList<CardInfoPtr> getCardInfos(const QStringList &cardNames) const;
|
|
|
|
/**
|
|
* @brief Retrieves a card using simplified name matching.
|
|
*
|
|
* The name is automatically normalized, so callers do not need to simplify it.
|
|
*
|
|
* @param cardName A (possibly simplified or misspelled) card name.
|
|
* @return A CardInfoPtr, or null if not found.
|
|
*/
|
|
[[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const;
|
|
|
|
/**
|
|
* @brief Looks up a card using exact name first, then simplified matching as fallback.
|
|
*
|
|
* @param name Raw card name input.
|
|
* @return The best-match CardInfoPtr, or null if no match is found.
|
|
*/
|
|
[[nodiscard]] CardInfoPtr lookupCardByName(const QString &name) const;
|
|
|
|
/**
|
|
* @brief Converts a CardRef into an ExactCard.
|
|
*
|
|
* If the providerId is empty, the preferred printing is used.
|
|
* If providerId exists but cannot be found, an ExactCard with an empty PrintingInfo is returned.
|
|
*
|
|
* @param cardRef Card reference with name and optional providerId.
|
|
* @return The resolved ExactCard, or empty if no card was found.
|
|
*/
|
|
[[nodiscard]] ExactCard getCard(const CardRef &cardRef) const;
|
|
|
|
/**
|
|
* @brief Resolves multiple CardRefs into ExactCards.
|
|
*
|
|
* Failed entries are not included in the result.
|
|
*
|
|
* @param cardRefs List of card references.
|
|
* @return List of successfully resolved ExactCards.
|
|
*/
|
|
[[nodiscard]] QList<ExactCard> getCards(const QList<CardRef> &cardRefs) const;
|
|
|
|
/**
|
|
* @brief Attempts a more flexible card lookup using both simple name matching and CardRef rules.
|
|
*
|
|
* If providerId is missing, uses preferred printing. If lookup fails, attempts simplified name.
|
|
*
|
|
* @param cardRef Card reference to resolve.
|
|
* @return The best-guess ExactCard, or empty if unresolved.
|
|
*/
|
|
[[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const;
|
|
|
|
/**
|
|
* @brief Returns a random card from the database using the preferred printing.
|
|
*
|
|
* @return A random ExactCard, or empty if the database is empty.
|
|
*/
|
|
[[nodiscard]] ExactCard getRandomCard() const;
|
|
|
|
/**
|
|
* @brief Returns a printing of a card from the same set as another given printing when possible.
|
|
*
|
|
* If no matching printing exists, falls back to a standard lookup.
|
|
*
|
|
* @param cardName Card to retrieve.
|
|
* @param otherPrinting Printing to match the set against.
|
|
* @return Matching ExactCard if found, otherwise fallback ExactCard.
|
|
*/
|
|
[[nodiscard]] ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const;
|
|
|
|
/**
|
|
* @brief Returns the preferred printing of a card based on user preferences and set priority.
|
|
*
|
|
* @param cardName Name of the card.
|
|
* @return The preferred ExactCard.
|
|
*/
|
|
[[nodiscard]] ExactCard getPreferredCard(const QString &cardName) const;
|
|
|
|
/**
|
|
* @brief Returns the preferred printing of a card based on user preferences and set priority.
|
|
*
|
|
* @param cardInfo Card information object.
|
|
* @return The preferred ExactCard.
|
|
*/
|
|
[[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &cardInfo) const;
|
|
|
|
/**
|
|
* @brief Checks whether the CardRef refers to the preferred printing.
|
|
*
|
|
* @param cardRef Card reference to test.
|
|
* @return True if providerId matches the preferred printing.
|
|
*/
|
|
[[nodiscard]] bool isPreferredPrinting(const CardRef &cardRef) const;
|
|
|
|
/**
|
|
* @brief Returns the preferred printing for the given card name.
|
|
*
|
|
* @param cardName Card name.
|
|
* @return Preferred PrintingInfo, or empty if not found.
|
|
*/
|
|
[[nodiscard]] PrintingInfo getPreferredPrinting(const QString &cardName) const;
|
|
|
|
/**
|
|
* @brief Returns the preferred printing for the given card.
|
|
*
|
|
* @param cardInfo Card information object.
|
|
* @return Preferred PrintingInfo, or empty if not applicable.
|
|
*/
|
|
[[nodiscard]] PrintingInfo getPreferredPrinting(const CardInfoPtr &cardInfo) const;
|
|
|
|
/**
|
|
* @brief Returns the providerId of the preferred printing.
|
|
*
|
|
* @param cardName Card name.
|
|
* @return ProviderId string for preferred printing.
|
|
*/
|
|
[[nodiscard]] QString getPreferredPrintingProviderId(const QString &cardName) const;
|
|
|
|
/**
|
|
* @brief Retrieves a specific printing referenced by CardRef.
|
|
*
|
|
* @param cardRef Card reference including providerId.
|
|
* @return Matching PrintingInfo, or empty if not found.
|
|
*/
|
|
[[nodiscard]] PrintingInfo getSpecificPrinting(const CardRef &cardRef) const;
|
|
|
|
/**
|
|
* @brief Searches for a specific printing by set code and collector number.
|
|
*
|
|
* @param cardName Card name to search.
|
|
* @param setCode Set (short) code to match.
|
|
* @param collectorNumber Collector number. If empty, any printing from the set is returned.
|
|
* @return Matching PrintingInfo, or empty if not found.
|
|
*/
|
|
[[nodiscard]] PrintingInfo
|
|
getSpecificPrinting(const QString &cardName, const QString &setCode, const QString &collectorNumber) const;
|
|
|
|
/**
|
|
* @brief Searches for a printing that matches a given providerId.
|
|
*
|
|
* @param card Card to search.
|
|
* @param providerId Provider identifier to match.
|
|
* @return Matching PrintingInfo, or empty if not found.
|
|
*/
|
|
[[nodiscard]] PrintingInfo findPrintingWithId(const CardInfoPtr &card, const QString &providerId) const;
|
|
|
|
/**
|
|
* @brief Returns a list of all main card types present in the database.
|
|
*
|
|
* @return List of main card type strings.
|
|
*/
|
|
[[nodiscard]] QStringList getAllMainCardTypes() const;
|
|
|
|
/**
|
|
* @brief Returns a mapping of main card types to their occurrence counts.
|
|
*
|
|
* @return Map of main card type to count.
|
|
*/
|
|
[[nodiscard]] QMap<QString, int> getAllMainCardTypesWithCount() const;
|
|
|
|
/**
|
|
* @brief Returns a mapping of card subtypes to their occurrence counts.
|
|
*
|
|
* @return Map of subtype string to count.
|
|
*/
|
|
[[nodiscard]] QMap<QString, int> getAllSubCardTypesWithCount() const;
|
|
|
|
/**
|
|
* @brief Returns a mapping of Scryfall Tagger tag slugs to their occurrence counts.
|
|
*
|
|
* Tags are stored space-separated in the `tags` card property, so a card
|
|
* tagged "ramp" and "removal" contributes one to each slug's count.
|
|
*
|
|
* @return Map of tag slug to count.
|
|
*/
|
|
[[nodiscard]] QMap<QString, int> getAllTagsWithCount() const;
|
|
FormatRulesPtr getFormat(const QString &formatName) const;
|
|
QMap<QString, int> getAllFormatsWithCount() const;
|
|
|
|
private:
|
|
const CardDatabase *db; //!< Card database used for all lookups.
|
|
const ICardPreferenceProvider *prefs; //!< Preference provider for preferred printings.
|
|
|
|
// Count maps are expensive to compute (they iterate the whole database) and are
|
|
// queried every time a filter widget is built, so cache them and invalidate on
|
|
// any database mutation. Only the main thread reads or writes these.
|
|
mutable QMap<QString, int> mainCardTypeCountsCache;
|
|
mutable QMap<QString, int> subCardTypeCountsCache;
|
|
mutable QMap<QString, int> formatsCountCache;
|
|
mutable QMap<QString, int> tagCountsCache;
|
|
|
|
private slots:
|
|
void invalidateCaches();
|
|
};
|
|
|
|
#endif // COCKATRICE_CARD_DATABASE_QUERIER_H
|