[Refactor] Untangle card_info.cpp and split into individual files. (#6202)

* Untangle the card_info.cpp mess and split into individual files.

Took 53 minutes

* Auto-lint was disabled and my pre-commit hook didn't fire. Oh well.

Took 3 minutes

* Fix oracle.

Took 35 seconds

* Lint!

Took 20 seconds

* Fix tests.

Took 3 minutes

* CMakeLists.txt: The reason why I have to disable auto-lint.

Took 2 minutes

* dbconverter.

Took 3 minutes

* Oracle again.

Took 3 minutes

* dbconverter again.

Took 3 minutes

* dbconverter again again.

Took 2 minutes

* More fixes.

Took 4 minutes

Took 21 seconds

* Everything needs everything.

Took 3 minutes

* Everything means everything.

Took 4 minutes

* All the tests.

Took 4 minutes

* I hate everything about this.

Took 3 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL
2025-10-01 11:49:39 +02:00
committed by GitHub
parent 835e4af3e4
commit 89a8d0f6b8
30 changed files with 743 additions and 516 deletions

View File

@@ -8,7 +8,11 @@ set(cockatrice_SOURCES
${VERSION_STRING_CPP}
# sort by alphabetical order, so that there is no debate about where to add new sources to the list
src/card/card_info.cpp
src/card/card_relation.cpp
src/card/card_set.cpp
src/card/card_set_list.cpp
src/card/exact_card.cpp
src/card/printing_info.cpp
src/client/deck_editor_menu.cpp
src/client/get_text_with_max.cpp
src/client/network/client_update_checker.cpp

View File

@@ -2,230 +2,23 @@
#include "../picture_loader/picture_loader.h"
#include "../settings/cache_settings.h"
#include "card_relation.h"
#include "game_specific_terms.h"
#include "printing_info.h"
#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include <QRegularExpression>
#include <QSharedPointer>
#include <QString>
#include <QVariant>
#include <algorithm>
#include <utility>
const char *CardSet::TOKENS_SETNAME = "TK";
class CardRelation;
class CardSet;
class CardInfo;
CardSet::CardSet(const QString &_shortName,
const QString &_longName,
const QString &_setType,
const QDate &_releaseDate,
const CardSet::Priority _priority)
: shortName(_shortName), longName(_longName), releaseDate(_releaseDate), setType(_setType), priority(_priority)
{
loadSetOptions();
}
CardSetPtr CardSet::newInstance(const QString &_shortName,
const QString &_longName,
const QString &_setType,
const QDate &_releaseDate,
const Priority _priority)
{
CardSetPtr ptr(new CardSet(_shortName, _longName, _setType, _releaseDate, _priority));
// ptr->setSmartPointer(ptr);
return ptr;
}
QString CardSet::getCorrectedShortName() const
{
// For Windows machines.
QSet<QString> invalidFileNames;
invalidFileNames << "CON"
<< "PRN"
<< "AUX"
<< "NUL"
<< "COM1"
<< "COM2"
<< "COM3"
<< "COM4"
<< "COM5"
<< "COM6"
<< "COM7"
<< "COM8"
<< "COM9"
<< "LPT1"
<< "LPT2"
<< "LPT3"
<< "LPT4"
<< "LPT5"
<< "LPT6"
<< "LPT7"
<< "LPT8"
<< "LPT9";
return invalidFileNames.contains(shortName) ? shortName + "_" : shortName;
}
void CardSet::loadSetOptions()
{
sortKey = SettingsCache::instance().cardDatabase().getSortKey(shortName);
enabled = SettingsCache::instance().cardDatabase().isEnabled(shortName);
isknown = SettingsCache::instance().cardDatabase().isKnown(shortName);
}
void CardSet::setSortKey(unsigned int _sortKey)
{
sortKey = _sortKey;
SettingsCache::instance().cardDatabase().setSortKey(shortName, _sortKey);
}
void CardSet::setEnabled(bool _enabled)
{
enabled = _enabled;
SettingsCache::instance().cardDatabase().setEnabled(shortName, _enabled);
}
void CardSet::setIsKnown(bool _isknown)
{
isknown = _isknown;
SettingsCache::instance().cardDatabase().setIsKnown(shortName, _isknown);
}
class SetList::KeyCompareFunctor
{
public:
inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const
{
if (a.isNull() || b.isNull()) {
qCWarning(CardInfoLog) << "SetList::KeyCompareFunctor a or b is null";
return false;
}
return a->getSortKey() < b->getSortKey();
}
};
void SetList::sortByKey()
{
std::sort(begin(), end(), KeyCompareFunctor());
}
int SetList::getEnabledSetsNum()
{
int num = 0;
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && set->getEnabled()) {
++num;
}
}
return num;
}
int SetList::getUnknownSetsNum()
{
int num = 0;
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
++num;
}
}
return num;
}
QStringList SetList::getUnknownSetsNames()
{
QStringList sets = QStringList();
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
sets << set->getShortName();
}
}
return sets;
}
void SetList::enableAllUnknown()
{
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
set->setIsKnown(true);
set->setEnabled(true);
} else if (set && set->getIsKnownIgnored() && !set->getEnabled()) {
set->setEnabled(true);
}
}
}
void SetList::enableAll()
{
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set == nullptr) {
qCWarning(CardInfoLog) << "enabledAll has null";
continue;
}
if (!set->getIsKnownIgnored()) {
set->setIsKnown(true);
}
set->setEnabled(true);
}
}
void SetList::markAllAsKnown()
{
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
set->setIsKnown(true);
set->setEnabled(false);
} else if (set && set->getIsKnownIgnored() && !set->getEnabled()) {
set->setEnabled(true);
}
}
}
void SetList::guessSortKeys()
{
defaultSort();
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set.isNull()) {
qCWarning(CardInfoLog) << "guessSortKeys set is null";
continue;
}
set->setSortKey(i);
}
}
void SetList::defaultSort()
{
std::sort(begin(), end(), [](const CardSetPtr &a, const CardSetPtr &b) {
// Sort by priority, then by release date, then by short name
if (a->getPriority() != b->getPriority()) {
return a->getPriority() < b->getPriority(); // lowest first
} else if (a->getReleaseDate() != b->getReleaseDate()) {
return a->getReleaseDate() > b->getReleaseDate(); // most recent first
} else {
return a->getShortName() < b->getShortName(); // alphabetically
}
});
}
PrintingInfo::PrintingInfo(const CardSetPtr &_set) : set(_set)
{
}
/**
* Gets the uuid property of the printing, or an empty string if the property isn't present
*/
QString PrintingInfo::getUuid() const
{
return properties.value("uuid").toString();
}
using CardInfoPtr = QSharedPointer<CardInfo>;
CardInfo::CardInfo(const QString &_name,
const QString &_text,
@@ -364,17 +157,6 @@ const QChar CardInfo::getColorChar() const
}
}
CardRelation::CardRelation(const QString &_name,
AttachType _attachType,
bool _isCreateAllExclusion,
bool _isVariableCount,
int _defaultCount,
bool _isPersistent)
: name(_name), attachType(_attachType), isCreateAllExclusion(_isCreateAllExclusion),
isVariableCount(_isVariableCount), defaultCount(_defaultCount), isPersistent(_isPersistent)
{
}
void CardInfo::resetReverseRelatedCards2Me()
{
for (CardRelation *cardRelation : this->getReverseRelatedCards2Me()) {

View File

@@ -7,6 +7,8 @@
#ifndef CARD_INFO_H
#define CARD_INFO_H
#include "printing_info.h"
#include <QDate>
#include <QHash>
#include <QList>
@@ -21,7 +23,6 @@
inline Q_LOGGING_CATEGORY(CardInfoLog, "card_info");
class CardInfo;
class PrintingInfo;
class CardSet;
class CardRelation;
class ICardDatabaseParser;
@@ -35,191 +36,56 @@ typedef QHash<QString, CardSetPtr> SetNameMap;
Q_DECLARE_METATYPE(CardInfoPtr)
class CardSet : public QList<CardInfoPtr>
{
public:
enum Priority
{
PriorityFallback = 0,
PriorityPrimary = 10,
PrioritySecondary = 20,
PriorityReprint = 30,
PriorityOther = 40,
PriorityLowest = 100,
};
static const char *TOKENS_SETNAME;
private:
QString shortName, longName;
unsigned int sortKey;
QDate releaseDate;
QString setType;
Priority priority;
bool enabled, isknown;
public:
explicit CardSet(const QString &_shortName = QString(),
const QString &_longName = QString(),
const QString &_setType = QString(),
const QDate &_releaseDate = QDate(),
const Priority _priority = PriorityFallback);
static CardSetPtr newInstance(const QString &_shortName = QString(),
const QString &_longName = QString(),
const QString &_setType = QString(),
const QDate &_releaseDate = QDate(),
const Priority _priority = PriorityFallback);
QString getCorrectedShortName() const;
QString getShortName() const
{
return shortName;
}
QString getLongName() const
{
return longName;
}
QString getSetType() const
{
return setType;
}
QDate getReleaseDate() const
{
return releaseDate;
}
Priority getPriority() const
{
return priority;
}
void setLongName(const QString &_longName)
{
longName = _longName;
}
void setSetType(const QString &_setType)
{
setType = _setType;
}
void setReleaseDate(const QDate &_releaseDate)
{
releaseDate = _releaseDate;
}
void setPriority(const Priority _priority)
{
priority = _priority;
}
void loadSetOptions();
int getSortKey() const
{
return sortKey;
}
void setSortKey(unsigned int _sortKey);
bool getEnabled() const
{
return enabled;
}
void setEnabled(bool _enabled);
bool getIsKnown() const
{
return isknown;
}
void setIsKnown(bool _isknown);
// Determine incomplete sets.
bool getIsKnownIgnored() const
{
return longName.length() + setType.length() + releaseDate.toString().length() == 0;
}
};
class SetList : public QList<CardSetPtr>
{
private:
class KeyCompareFunctor;
public:
void sortByKey();
void guessSortKeys();
void enableAllUnknown();
void enableAll();
void markAllAsKnown();
int getEnabledSetsNum();
int getUnknownSetsNum();
QStringList getUnknownSetsNames();
void defaultSort();
};
/**
* Info relating to a specific printing for a card.
* @class CardInfo
* @ingroup Cards
*
* @brief Represents a card and its associated metadata, properties, and relationships.
*
* CardInfo holds both static information (name, text, flags) and dynamic data
* (properties, set memberships, relationships). It also integrates with
* signals/slots, allowing observers to react to property or visual updates.
*
* Each CardInfo may belong to multiple sets through its printings, and can
* be related to other cards through defined relationships.
*/
class PrintingInfo
{
public:
explicit PrintingInfo(const CardSetPtr &_set = nullptr);
~PrintingInfo() = default;
bool operator==(const PrintingInfo &other) const
{
return this->set == other.set && this->properties == other.properties;
}
private:
CardSetPtr set;
// per-printing card properties;
QVariantHash properties;
public:
CardSetPtr getSet() const
{
return set;
}
QStringList getProperties() const
{
return properties.keys();
}
QString getProperty(const QString &propertyName) const
{
return properties.value(propertyName).toString();
}
void setProperty(const QString &_name, const QString &_value)
{
properties.insert(_name, _value);
}
QString getUuid() const;
};
class CardInfo : public QObject
{
Q_OBJECT
private:
CardInfoPtr smartThis;
// The card name
QString name;
// The name without punctuation or capitalization, for better card name recognition.
QString simpleName;
// card text
QString text;
// whether this is not a "real" card but a token
bool isToken;
// basic card properties; common for all the sets
QVariantHash properties;
// the cards i'm related to
QList<CardRelation *> relatedCards;
// the card i'm reverse-related to
QList<CardRelation *> reverseRelatedCards;
// the cards thare are reverse-related to me
QList<CardRelation *> reverseRelatedCardsToMe;
// card sets
SetToPrintingsMap setsToPrintings;
// cached set names
QString setsNames;
// positioning properties; used by UI
bool cipt;
bool landscapeOrientation;
int tableRow;
bool upsideDownArt;
CardInfoPtr smartThis; ///< Smart pointer to self for safe cross-references.
QString name; ///< Full name of the card.
QString simpleName; ///< Simplified name for fuzzy matching.
QString text; ///< Text description or rules text of the card.
bool isToken; ///< Whether this card is a token or not.
QVariantHash properties; ///< Key-value store of dynamic card properties.
QList<CardRelation *> relatedCards; ///< Forward references to related cards.
QList<CardRelation *> reverseRelatedCards; ///< Cards that refer back to this card.
QList<CardRelation *> reverseRelatedCardsToMe; ///< Cards that consider this card as related.
SetToPrintingsMap setsToPrintings; ///< Mapping from set names to printing variations.
QString setsNames; ///< Cached, human-readable list of set names.
bool cipt; ///< Positioning flag used by UI.
bool landscapeOrientation; ///< Orientation flag for rendering.
int tableRow; ///< Row index in a table or visual representation.
bool upsideDownArt; ///< Whether artwork is flipped for visual purposes.
public:
/**
* @brief Constructs a CardInfo with full initialization.
*
* @param _name The name of the card.
* @param _text Rules text or description of the card.
* @param _isToken Flag indicating whether the card is a token.
* @param _properties Arbitrary key-value properties.
* @param _relatedCards Forward references to related cards.
* @param _reverseRelatedCards Backward references to related cards.
* @param _sets Map of set names to printing information.
* @param _cipt UI positioning flag.
* @param _landscapeOrientation UI rendering orientation.
* @param _tableRow Row index for table placement.
* @param _upsideDownArt Whether the artwork should be displayed upside down.
*/
explicit CardInfo(const QString &_name,
const QString &_text,
bool _isToken,
@@ -231,6 +97,14 @@ public:
bool _landscapeOrientation,
int _tableRow,
bool _upsideDownArt);
/**
* @brief Copy constructor for CardInfo.
*
* Performs a deep copy of properties, sets, and related card lists.
*
* @param other Another CardInfo to copy.
*/
CardInfo(const CardInfo &other)
: QObject(other.parent()), name(other.name), simpleName(other.simpleName), text(other.text),
isToken(other.isToken), properties(other.properties), relatedCards(other.relatedCards),
@@ -240,8 +114,32 @@ public:
{
}
/**
* @brief Creates a new instance with only the card name.
*
* All other fields are set to defaults.
*
* @param _name The card name.
* @return Shared pointer to the new CardInfo instance.
*/
static CardInfoPtr newInstance(const QString &_name);
/**
* @brief Creates a new instance with full initialization.
*
* @param _name Name of the card.
* @param _text Rules text or description.
* @param _isToken Token flag.
* @param _properties Arbitrary properties.
* @param _relatedCards Forward relationships.
* @param _reverseRelatedCards Reverse relationships.
* @param _sets Printing information per set.
* @param _cipt UI positioning flag.
* @param _landscapeOrientation UI rendering orientation.
* @param _tableRow Row index for table placement.
* @param _upsideDownArt Artwork orientation flag.
* @return Shared pointer to the new CardInfo instance.
*/
static CardInfoPtr newInstance(const QString &_name,
const QString &_text,
bool _isToken,
@@ -254,20 +152,33 @@ public:
int _tableRow,
bool _upsideDownArt);
/**
* @brief Clones the current CardInfo instance.
*
* Uses the copy constructor and ensures the smart pointer is properly set.
*
* @return Shared pointer to the cloned CardInfo.
*/
CardInfoPtr clone() const
{
// Use the copy constructor to create a new instance
CardInfoPtr newCardInfo = CardInfoPtr(new CardInfo(*this));
newCardInfo->setSmartPointer(newCardInfo); // Set the smart pointer for the new instance
return newCardInfo;
}
/**
* @brief Sets the internal smart pointer to self.
*
* Used internally to allow safe cross-references among CardInfo and CardSet.
*
* @param _ptr Shared pointer pointing to this instance.
*/
void setSmartPointer(CardInfoPtr _ptr)
{
smartThis = std::move(_ptr);
}
// basic properties
/** @name Basic Properties Accessors */ //@{
inline const QString &getName() const
{
return name;
@@ -276,7 +187,6 @@ public:
{
return simpleName;
}
const QString &getText() const
{
return text;
@@ -286,7 +196,6 @@ public:
text = _text;
emit cardInfoChanged(smartThis);
}
bool getIsToken() const
{
return isToken;
@@ -316,8 +225,9 @@ public:
{
return setsNames;
}
//@}
// related cards
/** @name Related Cards Accessors */ //@{
const QList<CardRelation *> &getRelatedCards() const
{
return relatedCards;
@@ -342,8 +252,9 @@ public:
{
reverseRelatedCardsToMe.append(cardRelation);
}
//@}
// positioning
/** @name UI Positioning */ //@{
bool getCipt() const
{
return cipt;
@@ -365,8 +276,9 @@ public:
return upsideDownArt;
}
const QChar getColorChar() const;
//@}
// Back-compatibility methods. Remove ASAP
/** @name Legacy/Convenience Property Accessors */ //@{
const QString getCardType() const;
void setCardType(const QString &value);
const QString getCmc() const;
@@ -377,100 +289,66 @@ public:
const QString getManaCost() const;
const QString getPowTough() const;
void setPowTough(const QString &value);
//@}
/**
* @brief Returns a version of the card name safe for file storage or fuzzy matching.
*
* Removes invalid characters, replaces spacing markers, and normalizes diacritics.
*
* @return Corrected card name as a QString.
*/
QString getCorrectedName() const;
/**
* @brief Adds a printing to a specific set.
*
* Updates the mapping and refreshes the cached list of set names.
*
* @param _set The set to which the card should be added.
* @param _info Optional printing information.
*/
void addToSet(const CardSetPtr &_set, PrintingInfo _info = PrintingInfo());
/**
* @brief Combines legality properties from a provided map.
*
* Useful for merging format legality flags from multiple sources.
*
* @param props Key-value mapping of format legalities.
*/
void combineLegalities(const QVariantHash &props);
/**
* @brief Refreshes the cached, human-readable list of set names.
*
* Typically called after adding or modifying set memberships.
*/
void refreshCachedSetNames();
/**
* Simplify a name to have no punctuation and lowercase all letters, for
* less strict name-matching.
* @brief Simplifies a name for fuzzy matching.
*
* Converts to lowercase, removes punctuation/spacing.
*
* @param name Original name string.
* @return Simplified name string.
*/
static QString simplifyName(const QString &name);
signals:
/**
* Emit this when a pixmap for this card finishes loading.
* @param printing The specific printing the pixmap is for.
* @brief Emitted when a pixmap for this card has been updated or finished loading.
*
* @param printing Specific printing for which the pixmap has updated.
*/
void pixmapUpdated(const PrintingInfo &printing);
/**
* @brief Emitted when card properties or state have changed.
*
* @param card Shared pointer to the CardInfo instance that changed.
*/
void cardInfoChanged(CardInfoPtr card);
};
class CardRelation : public QObject
{
Q_OBJECT
public:
enum AttachType
{
DoesNotAttach = 0,
AttachTo = 1,
TransformInto = 2,
};
private:
QString name;
AttachType attachType;
bool isCreateAllExclusion;
bool isVariableCount;
int defaultCount;
bool isPersistent;
public:
explicit CardRelation(const QString &_name = QString(),
AttachType _attachType = DoesNotAttach,
bool _isCreateAllExclusion = false,
bool _isVariableCount = false,
int _defaultCount = 1,
bool _isPersistent = false);
inline const QString &getName() const
{
return name;
}
AttachType getAttachType() const
{
return attachType;
}
bool getDoesAttach() const
{
return attachType != DoesNotAttach;
}
bool getDoesTransform() const
{
return attachType == TransformInto;
}
QString getAttachTypeAsString() const
{
switch (attachType) {
case AttachTo:
return "attach";
case TransformInto:
return "transform";
default:
return "";
}
}
bool getCanCreateAnother() const
{
return !getDoesAttach();
}
bool getIsCreateAllExclusion() const
{
return isCreateAllExclusion;
}
bool getIsVariable() const
{
return isVariableCount;
}
int getDefaultCount() const
{
return defaultCount;
}
bool getIsPersistent() const
{
return isPersistent;
}
};
#endif

View File

@@ -0,0 +1,12 @@
#include "card_relation.h"
CardRelation::CardRelation(const QString &_name,
CardRelationType _attachType,
bool _isCreateAllExclusion,
bool _isVariableCount,
int _defaultCount,
bool _isPersistent)
: name(_name), attachType(_attachType), isCreateAllExclusion(_isCreateAllExclusion),
isVariableCount(_isVariableCount), defaultCount(_defaultCount), isPersistent(_isPersistent)
{
}

View File

@@ -0,0 +1,73 @@
#ifndef COCKATRICE_CARD_RELATION_H
#define COCKATRICE_CARD_RELATION_H
#include "card_relation_type.h"
#include <QObject>
#include <QString>
class CardRelation : public QObject
{
Q_OBJECT
private:
QString name;
CardRelationType attachType;
bool isCreateAllExclusion;
bool isVariableCount;
int defaultCount;
bool isPersistent;
public:
explicit CardRelation(const QString &_name = QString(),
CardRelationType _attachType = CardRelationType::DoesNotAttach,
bool _isCreateAllExclusion = false,
bool _isVariableCount = false,
int _defaultCount = 1,
bool _isPersistent = false);
const QString &getName() const
{
return name;
}
CardRelationType getAttachType() const
{
return attachType;
}
bool getDoesAttach() const
{
return attachType != CardRelationType::DoesNotAttach;
}
bool getDoesTransform() const
{
return attachType == CardRelationType::TransformInto;
}
QString getAttachTypeAsString() const
{
return cardAttachTypeToString(attachType);
}
bool getCanCreateAnother() const
{
return !getDoesAttach();
}
bool getIsCreateAllExclusion() const
{
return isCreateAllExclusion;
}
bool getIsVariable() const
{
return isVariableCount;
}
int getDefaultCount() const
{
return defaultCount;
}
bool getIsPersistent() const
{
return isPersistent;
}
};
#endif // COCKATRICE_CARD_RELATION_H

View File

@@ -0,0 +1,29 @@
#ifndef COCKATRICE_CARD_RELATION_TYPE_H
#define COCKATRICE_CARD_RELATION_TYPE_H
#include <QString>
/**
* Represents how a card relates to another (attach, transform, etc.).
*/
enum class CardRelationType
{
DoesNotAttach = 0,
AttachTo = 1,
TransformInto = 2,
};
// Optional helper
inline QString cardAttachTypeToString(CardRelationType type)
{
switch (type) {
case CardRelationType::AttachTo:
return "attach";
case CardRelationType::TransformInto:
return "transform";
default:
return "";
}
}
#endif // COCKATRICE_CARD_RELATION_TYPE_H

View File

@@ -0,0 +1,81 @@
#include "card_set.h"
#include "../settings/cache_settings.h"
const char *CardSet::TOKENS_SETNAME = "TK";
CardSet::CardSet(const QString &_shortName,
const QString &_longName,
const QString &_setType,
const QDate &_releaseDate,
const CardSet::Priority _priority)
: shortName(_shortName), longName(_longName), releaseDate(_releaseDate), setType(_setType), priority(_priority)
{
loadSetOptions();
}
CardSetPtr CardSet::newInstance(const QString &_shortName,
const QString &_longName,
const QString &_setType,
const QDate &_releaseDate,
const Priority _priority)
{
CardSetPtr ptr(new CardSet(_shortName, _longName, _setType, _releaseDate, _priority));
// ptr->setSmartPointer(ptr);
return ptr;
}
QString CardSet::getCorrectedShortName() const
{
// For Windows machines.
QSet<QString> invalidFileNames;
invalidFileNames << "CON"
<< "PRN"
<< "AUX"
<< "NUL"
<< "COM1"
<< "COM2"
<< "COM3"
<< "COM4"
<< "COM5"
<< "COM6"
<< "COM7"
<< "COM8"
<< "COM9"
<< "LPT1"
<< "LPT2"
<< "LPT3"
<< "LPT4"
<< "LPT5"
<< "LPT6"
<< "LPT7"
<< "LPT8"
<< "LPT9";
return invalidFileNames.contains(shortName) ? shortName + "_" : shortName;
}
void CardSet::loadSetOptions()
{
sortKey = SettingsCache::instance().cardDatabase().getSortKey(shortName);
enabled = SettingsCache::instance().cardDatabase().isEnabled(shortName);
isknown = SettingsCache::instance().cardDatabase().isKnown(shortName);
}
void CardSet::setSortKey(unsigned int _sortKey)
{
sortKey = _sortKey;
SettingsCache::instance().cardDatabase().setSortKey(shortName, _sortKey);
}
void CardSet::setEnabled(bool _enabled)
{
enabled = _enabled;
SettingsCache::instance().cardDatabase().setEnabled(shortName, _enabled);
}
void CardSet::setIsKnown(bool _isknown)
{
isknown = _isknown;
SettingsCache::instance().cardDatabase().setIsKnown(shortName, _isknown);
}

View File

@@ -0,0 +1,116 @@
#ifndef COCKATRICE_CARD_SET_H
#define COCKATRICE_CARD_SET_H
#include <QDate>
#include <QList>
#include <QSharedPointer>
#include <QString>
class CardInfo;
using CardInfoPtr = QSharedPointer<CardInfo>;
class CardSet;
using CardSetPtr = QSharedPointer<CardSet>;
class CardSet : public QList<CardInfoPtr>
{
public:
enum Priority
{
PriorityFallback = 0,
PriorityPrimary = 10,
PrioritySecondary = 20,
PriorityReprint = 30,
PriorityOther = 40,
PriorityLowest = 100,
};
static const char *TOKENS_SETNAME;
private:
QString shortName, longName;
unsigned int sortKey;
QDate releaseDate;
QString setType;
Priority priority;
bool enabled, isknown;
public:
explicit CardSet(const QString &_shortName = QString(),
const QString &_longName = QString(),
const QString &_setType = QString(),
const QDate &_releaseDate = QDate(),
const Priority _priority = PriorityFallback);
static CardSetPtr newInstance(const QString &_shortName = QString(),
const QString &_longName = QString(),
const QString &_setType = QString(),
const QDate &_releaseDate = QDate(),
const Priority _priority = PriorityFallback);
QString getCorrectedShortName() const;
QString getShortName() const
{
return shortName;
}
QString getLongName() const
{
return longName;
}
QString getSetType() const
{
return setType;
}
QDate getReleaseDate() const
{
return releaseDate;
}
Priority getPriority() const
{
return priority;
}
void setLongName(const QString &_longName)
{
longName = _longName;
}
void setSetType(const QString &_setType)
{
setType = _setType;
}
void setReleaseDate(const QDate &_releaseDate)
{
releaseDate = _releaseDate;
}
void setPriority(const Priority _priority)
{
priority = _priority;
}
void loadSetOptions();
int getSortKey() const
{
return sortKey;
}
void setSortKey(unsigned int _sortKey);
bool getEnabled() const
{
return enabled;
}
void setEnabled(bool _enabled);
bool getIsKnown() const
{
return isknown;
}
void setIsKnown(bool _isknown);
bool getIsKnownIgnored() const
{
return longName.length() + setType.length() + releaseDate.toString().length() == 0;
}
};
#endif // COCKATRICE_CARD_SET_H

View File

@@ -0,0 +1,127 @@
#include "card_set_list.h"
class CardSetList::KeyCompareFunctor
{
public:
inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const
{
if (a.isNull() || b.isNull()) {
// qCWarning(CardInfoLog) << "SetList::KeyCompareFunctor a or b is null";
return false;
}
return a->getSortKey() < b->getSortKey();
}
};
void CardSetList::sortByKey()
{
std::sort(begin(), end(), KeyCompareFunctor());
}
int CardSetList::getEnabledSetsNum()
{
int num = 0;
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && set->getEnabled()) {
++num;
}
}
return num;
}
int CardSetList::getUnknownSetsNum()
{
int num = 0;
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
++num;
}
}
return num;
}
QStringList CardSetList::getUnknownSetsNames()
{
QStringList sets = QStringList();
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
sets << set->getShortName();
}
}
return sets;
}
void CardSetList::enableAllUnknown()
{
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
set->setIsKnown(true);
set->setEnabled(true);
} else if (set && set->getIsKnownIgnored() && !set->getEnabled()) {
set->setEnabled(true);
}
}
}
void CardSetList::enableAll()
{
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set == nullptr) {
// qCWarning(CardInfoLog) << "enabledAll has null";
continue;
}
if (!set->getIsKnownIgnored()) {
set->setIsKnown(true);
}
set->setEnabled(true);
}
}
void CardSetList::markAllAsKnown()
{
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
set->setIsKnown(true);
set->setEnabled(false);
} else if (set && set->getIsKnownIgnored() && !set->getEnabled()) {
set->setEnabled(true);
}
}
}
void CardSetList::guessSortKeys()
{
defaultSort();
for (int i = 0; i < size(); ++i) {
CardSetPtr set = at(i);
if (set.isNull()) {
// qCWarning(CardInfoLog) << "guessSortKeys set is null";
continue;
}
set->setSortKey(i);
}
}
void CardSetList::defaultSort()
{
std::sort(begin(), end(), [](const CardSetPtr &a, const CardSetPtr &b) {
// Sort by priority, then by release date, then by short name
if (a->getPriority() != b->getPriority()) {
return a->getPriority() < b->getPriority(); // lowest first
} else if (a->getReleaseDate() != b->getReleaseDate()) {
return a->getReleaseDate() > b->getReleaseDate(); // most recent first
} else {
return a->getShortName() < b->getShortName(); // alphabetically
}
});
}

View File

@@ -0,0 +1,26 @@
#ifndef COCKATRICE_CARD_SET_LIST_H
#define COCKATRICE_CARD_SET_LIST_H
#include "card_set.h"
#include <QList>
#include <QStringList>
class CardSetList : public QList<CardSetPtr>
{
private:
class KeyCompareFunctor;
public:
void sortByKey();
void guessSortKeys();
void enableAllUnknown();
void enableAll();
void markAllAsKnown();
int getEnabledSetsNum();
int getUnknownSetsNum();
QStringList getUnknownSetsNames();
void defaultSort();
};
#endif // COCKATRICE_CARD_SET_LIST_H

View File

@@ -0,0 +1,13 @@
#include "printing_info.h"
PrintingInfo::PrintingInfo(const CardSetPtr &_set) : set(_set)
{
}
/**
* Gets the uuid property of the printing, or an empty string if the property isn't present
*/
QString PrintingInfo::getUuid() const
{
return properties.value("uuid").toString();
}

View File

@@ -0,0 +1,56 @@
#ifndef COCKATRICE_PRINTING_INFO_H
#define COCKATRICE_PRINTING_INFO_H
#include "card_set.h"
#include <QList>
#include <QMap>
#include <QStringList>
#include <QVariant>
class PrintingInfo;
using SetToPrintingsMap = QMap<QString, QList<PrintingInfo>>;
/**
* Info relating to a specific printing for a card.
*/
class PrintingInfo
{
public:
explicit PrintingInfo(const CardSetPtr &_set = nullptr);
~PrintingInfo() = default;
bool operator==(const PrintingInfo &other) const
{
return this->set == other.set && this->properties == other.properties;
}
private:
CardSetPtr set;
// per-printing card properties;
QVariantHash properties;
public:
CardSetPtr getSet() const
{
return set;
}
QStringList getProperties() const
{
return properties.keys();
}
QString getProperty(const QString &propertyName) const
{
return properties.value(propertyName).toString();
}
void setProperty(const QString &_name, const QString &_value)
{
properties.insert(_name, _value);
}
QString getUuid() const;
};
#endif // COCKATRICE_PRINTING_INFO_H

View File

@@ -43,7 +43,7 @@ class SetsModel : public QAbstractTableModel
private:
static const int NUM_COLS = 7;
SetList sets;
CardSetList sets;
QSet<CardSetPtr> enabledSets;
public:

View File

@@ -1,5 +1,6 @@
#include "card_database.h"
#include "../card/card_relation.h"
#include "../picture_loader/picture_loader.h"
#include "../settings/cache_settings.h"
#include "parser/cockatrice_xml_3.h"
@@ -144,9 +145,9 @@ CardSetPtr CardDatabase::getSet(const QString &setName)
}
}
SetList CardDatabase::getSetList() const
CardSetList CardDatabase::getSetList() const
{
SetList result;
CardSetList result;
for (auto set : sets.values()) {
result << set;
}

View File

@@ -7,6 +7,7 @@
#ifndef CARDDATABASE_H
#define CARDDATABASE_H
#include "../card/card_set_list.h"
#include "../card/exact_card.h"
#include "../common/card_ref.h"
#include "card_database_loader.h"
@@ -68,7 +69,7 @@ public:
return cards;
}
CardSetPtr getSet(const QString &setName);
SetList getSetList() const;
CardSetList getSetList() const;
LoadStatus getLoadStatus() const
{
return loadStatus;

View File

@@ -1,5 +1,8 @@
#include "cockatrice_xml_3.h"
#include "../../card/card_relation.h"
#include "../../card/card_relation_type.h"
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
@@ -232,7 +235,7 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
_sets[setName].append(setInfo);
// related cards
} else if (xmlName == "related" || xmlName == "reverse-related") {
CardRelation::AttachType attach = CardRelation::DoesNotAttach;
CardRelationType attach = CardRelationType::DoesNotAttach;
bool exclude = false;
bool variable = false;
int count = 1;
@@ -254,7 +257,7 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
}
if (attrs.hasAttribute("attach")) {
attach = CardRelation::AttachTo;
attach = CardRelationType::AttachTo;
}
if (attrs.hasAttribute("exclude")) {

View File

@@ -1,5 +1,6 @@
#include "cockatrice_xml_4.h"
#include "../../card/card_relation.h"
#include "../../settings/cache_settings.h"
#include <QCoreApplication>
@@ -205,7 +206,7 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
}
// related cards
} else if (xmlName == "related" || xmlName == "reverse-related") {
CardRelation::AttachType attachType = CardRelation::DoesNotAttach;
CardRelationType attachType = CardRelationType::DoesNotAttach;
bool exclude = false;
bool variable = false;
bool persistent = false;
@@ -228,8 +229,8 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
}
if (attrs.hasAttribute("attach")) {
attachType = attrs.value("attach").toString() == "transform" ? CardRelation::TransformInto
: CardRelation::AttachTo;
attachType = attrs.value("attach").toString() == "transform" ? CardRelationType::TransformInto
: CardRelationType::AttachTo;
}
if (attrs.hasAttribute("exclude")) {

View File

@@ -1,5 +1,6 @@
#include "card_menu.h"
#include "../../../card/card_relation.h"
#include "../../../database/card_database_manager.h"
#include "../../../settings/card_counter_settings.h"
#include "../../../tabs/tab_game.h"

View File

@@ -1,6 +1,7 @@
#include "player_actions.h"
#include "../../../common/pb/context_move_card.pb.h"
#include "../../card/card_relation.h"
#include "../../client/get_text_with_max.h"
#include "../../database/card_database_manager.h"
#include "../../tabs/tab_game.h"
@@ -977,7 +978,7 @@ void PlayerActions::actCreateAllRelatedCards()
dbName = cardRelationAll->getName();
bool persistent = cardRelationAll->getIsPersistent();
for (int i = 0; i < cardRelationAll->getDefaultCount(); ++i) {
createCard(sourceCard, dbName, CardRelation::DoesNotAttach, persistent);
createCard(sourceCard, dbName, CardRelationType::DoesNotAttach, persistent);
}
++tokensTypesCreated;
if (tokensTypesCreated == 1) {
@@ -992,7 +993,7 @@ void PlayerActions::actCreateAllRelatedCards()
dbName = cardRelationNotExcluded->getName();
bool persistent = cardRelationNotExcluded->getIsPersistent();
for (int i = 0; i < cardRelationNotExcluded->getDefaultCount(); ++i) {
createCard(sourceCard, dbName, CardRelation::DoesNotAttach, persistent);
createCard(sourceCard, dbName, CardRelationType::DoesNotAttach, persistent);
}
++tokensTypesCreated;
if (tokensTypesCreated == 1) {
@@ -1031,18 +1032,18 @@ bool PlayerActions::createRelatedFromRelation(const CardItem *sourceCard, const
return false;
}
for (int i = 0; i < count; ++i) {
createCard(sourceCard, dbName, CardRelation::DoesNotAttach, persistent);
createCard(sourceCard, dbName, CardRelationType::DoesNotAttach, persistent);
}
} else if (cardRelation->getDefaultCount() > 1) {
for (int i = 0; i < cardRelation->getDefaultCount(); ++i) {
createCard(sourceCard, dbName, CardRelation::DoesNotAttach, persistent);
createCard(sourceCard, dbName, CardRelationType::DoesNotAttach, persistent);
}
} else {
auto attachType = cardRelation->getAttachType();
// move card onto table first if attaching from some other zone
// we only do this for AttachTo because cross-zone TransformInto is already handled server-side
if (attachType == CardRelation::AttachTo && sourceCard->getZone()->getName() != "table") {
if (attachType == CardRelationType::AttachTo && sourceCard->getZone()->getName() != "table") {
playCardToTable(sourceCard, false);
}
@@ -1053,7 +1054,7 @@ bool PlayerActions::createRelatedFromRelation(const CardItem *sourceCard, const
void PlayerActions::createCard(const CardItem *sourceCard,
const QString &dbCardName,
CardRelation::AttachType attachType,
CardRelationType attachType,
bool persistent)
{
CardInfoPtr cardInfo = CardDatabaseManager::query()->getCardInfo(dbCardName);
@@ -1096,19 +1097,19 @@ void PlayerActions::createCard(const CardItem *sourceCard,
CardDatabaseManager::query()->getCardFromSameSet(cardInfo->getName(), sourceCard->getCard().getPrinting());
switch (attachType) {
case CardRelation::DoesNotAttach:
case CardRelationType::DoesNotAttach:
cmd.set_target_zone("table");
cmd.set_card_provider_id(relatedCard.getPrinting().getUuid().toStdString());
break;
case CardRelation::AttachTo:
case CardRelationType::AttachTo:
cmd.set_target_zone("table"); // We currently only support creating tokens on the table
cmd.set_card_provider_id(relatedCard.getPrinting().getUuid().toStdString());
cmd.set_target_card_id(sourceCard->getId());
cmd.set_target_mode(Command_CreateToken::ATTACH_TO);
break;
case CardRelation::TransformInto:
case CardRelationType::TransformInto:
// allow cards to directly transform on stack
cmd.set_zone(sourceCard->getZone()->getName() == "stack" ? "stack" : "table");
// Transform card zone changes are handled server-side

View File

@@ -7,6 +7,7 @@
#ifndef COCKATRICE_PLAYER_ACTIONS_H
#define COCKATRICE_PLAYER_ACTIONS_H
#include "../../card/card_relation_type.h"
#include "event_processing_options.h"
#include "player.h"
@@ -170,7 +171,7 @@ private:
void createCard(const CardItem *sourceCard,
const QString &dbCardName,
CardRelation::AttachType attach = CardRelation::DoesNotAttach,
CardRelationType attach = CardRelationType::DoesNotAttach,
bool persistent = false);
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation);

View File

@@ -1,5 +1,6 @@
#include "card_info_frame_widget.h"
#include "../../../card/card_relation.h"
#include "../../../database/card_database_manager.h"
#include "../../../game/board/card_item.h"
#include "../../../settings/cache_settings.h"

View File

@@ -1,5 +1,6 @@
#include "card_info_picture_widget.h"
#include "../../../card/card_relation.h"
#include "../../../database/card_database_manager.h"
#include "../../../game/board/card_item.h"
#include "../../../picture_loader/picture_loader.h"

View File

@@ -1,5 +1,6 @@
#include "card_info_text_widget.h"
#include "../../../card/card_relation.h"
#include "../../../card/game_specific_terms.h"
#include "../../../game/board/card_item.h"

View File

@@ -1,5 +1,6 @@
#include "deck_editor_database_display_widget.h"
#include "../../../card/card_relation.h"
#include "../../../database/card_database_manager.h"
#include "../../../filters/syntax_help.h"
#include "../../../settings/cache_settings.h"

View File

@@ -1,5 +1,6 @@
#include "printing_selector_card_overlay_widget.h"
#include "../../../card/card_relation.h"
#include "../../../database/card_database_manager.h"
#include "../../../settings/cache_settings.h"
#include "printing_selector_card_display_widget.h"

View File

@@ -87,7 +87,7 @@ void VisualDatabaseDisplaySetFilterWidget::retranslateUi()
void VisualDatabaseDisplaySetFilterWidget::createSetButtons()
{
SetList allSets = CardDatabaseManager::getInstance()->getSetList();
CardSetList allSets = CardDatabaseManager::getInstance()->getSetList();
// Sort by release date
std::sort(allSets.begin(), allSets.end(),
@@ -120,7 +120,7 @@ void VisualDatabaseDisplaySetFilterWidget::filterToRecentSets()
activeSets[set] = false;
}
SetList allSets = CardDatabaseManager::getInstance()->getSetList();
CardSetList allSets = CardDatabaseManager::getInstance()->getSetList();
// Sort by release date
std::sort(allSets.begin(), allSets.end(),

View File

@@ -6,7 +6,11 @@ set(dbconverter_SOURCES
src/main.cpp
src/mocks.cpp
../cockatrice/src/card/card_info.cpp
../cockatrice/src/card/card_relation.cpp
../cockatrice/src/card/card_set.cpp
../cockatrice/src/card/card_set_list.cpp
../cockatrice/src/card/exact_card.cpp
../cockatrice/src/card/printing_info.cpp
../cockatrice/src/database/card_database.cpp
../cockatrice/src/database/card_database_loader.cpp
../cockatrice/src/database/card_database_querier.cpp

View File

@@ -18,6 +18,9 @@ set(oracle_SOURCES
src/parsehelpers.cpp
src/qt-json/json.cpp
../cockatrice/src/card/card_info.cpp
../cockatrice/src/card/card_relation.cpp
../cockatrice/src/card/card_set.cpp
../cockatrice/src/card/printing_info.cpp
../cockatrice/src/client/network/release_channel.cpp
../cockatrice/src/database/parser/card_database_parser.cpp
../cockatrice/src/database/parser/cockatrice_xml_3.cpp

View File

@@ -7,6 +7,7 @@
#include <QDebug>
#include <QRegularExpression>
#include <algorithm>
#include <card/card_relation.h>
#include <climits>
SplitCardPart::SplitCardPart(const QString &_name,
@@ -379,12 +380,12 @@ int OracleImporter::importCardsFromSet(const CardSetPtr &currentSet, const QList
static const QRegularExpression meldNameRegex{"then meld them into ([^\\.]*)"};
QString additionalName = meldNameRegex.match(text).captured(1);
if (!additionalName.isNull()) {
relatedCards.append(new CardRelation(additionalName, CardRelation::TransformInto));
relatedCards.append(new CardRelation(additionalName, CardRelationType::TransformInto));
}
} else {
for (const QString &additionalName : name.split(" // ")) {
if (additionalName != faceName) {
relatedCards.append(new CardRelation(additionalName, CardRelation::TransformInto));
relatedCards.append(new CardRelation(additionalName, CardRelationType::TransformInto));
}
}
}
@@ -399,7 +400,7 @@ int OracleImporter::importCardsFromSet(const CardSetPtr &currentSet, const QList
auto spbk = givenRelated.value("spellbook").toStringList();
for (const QString &spbkName : spbk) {
relatedCards.append(
new CardRelation(spbkName, CardRelation::DoesNotAttach, false, false, 1, true));
new CardRelation(spbkName, CardRelationType::DoesNotAttach, false, false, 1, true));
}
}
}

View File

@@ -19,7 +19,11 @@ add_executable(
${MOCKS_SOURCES}
${VERSION_STRING_CPP}
../../cockatrice/src/card/card_info.cpp
../../cockatrice/src/card/card_relation.cpp
../../cockatrice/src/card/card_set.cpp
../../cockatrice/src/card/card_set_list.cpp
../../cockatrice/src/card/exact_card.cpp
../../cockatrice/src/card/printing_info.cpp
../../cockatrice/src/database/card_database.cpp
../../cockatrice/src/database/card_database_loader.cpp
../../cockatrice/src/database/card_database_querier.cpp
@@ -35,7 +39,11 @@ add_executable(
${MOCKS_SOURCES}
${VERSION_STRING_CPP}
../../cockatrice/src/card/card_info.cpp
../../cockatrice/src/card/card_relation.cpp
../../cockatrice/src/card/card_set.cpp
../../cockatrice/src/card/card_set_list.cpp
../../cockatrice/src/card/exact_card.cpp
../../cockatrice/src/card/printing_info.cpp
../../cockatrice/src/database/card_database.cpp
../../cockatrice/src/database/card_database_loader.cpp
../../cockatrice/src/database/card_database_querier.cpp