Cockatrice/common/decklist.h
Lukas Brübach edbc57edc7 DeckList now tries to assign reasonable defaults for UUID and collectorNumber if none are found in loaded DeckLists.
Rename overloaded DeckListModel findChild() function to findCardChildByNameAndUUID() for clarity.
2024-11-19 03:39:48 +01:00

333 lines
No EOL
9.8 KiB
C++

#ifndef DECKLIST_H
#define DECKLIST_H
#include <QDebug>
#include <QList>
#include <QMap>
#include <QObject>
#include <QPair>
#include <QSet>
#include <QStringList>
#include <QVector>
// Required on Mac. Forward declaration doesn't work. Don't ask why.
#include <QtCore/QXmlStreamReader>
#include <QtCore/QXmlStreamWriter>
#include <common/pb/move_card_to_zone.pb.h>
#include <utility>
class CardDatabase;
class QIODevice;
class QTextStream;
class InnerDecklistNode;
#define DECK_ZONE_MAIN "main"
#define DECK_ZONE_SIDE "side"
#define DECK_ZONE_TOKENS "tokens"
class SideboardPlan
{
private:
QString name;
QList<MoveCard_ToZone> moveList;
public:
explicit SideboardPlan(const QString &_name = QString(),
const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>());
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
QString getName() const
{
return name;
}
const QList<MoveCard_ToZone> &getMoveList() const
{
return moveList;
}
void setMoveList(const QList<MoveCard_ToZone> &_moveList);
};
enum DeckSortMethod
{
ByNumber,
ByName,
Default
};
class AbstractDecklistNode
{
protected:
InnerDecklistNode *parent;
DeckSortMethod sortMethod;
public:
explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr);
virtual ~AbstractDecklistNode() = default;
virtual void setSortMethod(DeckSortMethod method)
{
sortMethod = method;
}
virtual QString getName() const = 0;
virtual QString getCardUuid() const = 0;
virtual QString getCardCollectorNumber() const = 0;
InnerDecklistNode *getParent() const
{
return parent;
}
int depth() const;
virtual int height() const = 0;
virtual bool compare(AbstractDecklistNode *other) const = 0;
virtual bool readElement(QXmlStreamReader *xml) = 0;
virtual void writeElement(QXmlStreamWriter *xml) = 0;
};
class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDecklistNode *>
{
QString name;
QString cardSetCode;
QString cardCollectorNumber;
class compareFunctor;
public:
explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr)
: AbstractDecklistNode(_parent), name(std::move(_name))
{
}
explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr);
~InnerDecklistNode() override;
void setSortMethod(DeckSortMethod method) override;
[[nodiscard]] QString getName() const override
{
return name;
}
void setName(const QString &_name)
{
name = _name;
}
static QString visibleNameFromName(const QString &_name);
[[nodiscard]] virtual QString getVisibleName() const;
[[nodiscard]] QString getCardUuid() const override
{
return cardSetCode;
}
void setCardSetCode(const QString &_cardSetCode)
{
cardSetCode = _cardSetCode;
}
[[nodiscard]] QString getCardCollectorNumber() const override
{
return cardCollectorNumber;
}
void setCardCollectorNumber(const QString &_cardCollectorNumber)
{
cardCollectorNumber = _cardCollectorNumber;
}
void clearTree();
AbstractDecklistNode *findChild(const QString &_name);
AbstractDecklistNode *findCardChildByNameAndUUID(const QString &_name, const QString &_uuid);
int height() const override;
int recursiveCount(bool countTotalCards = false) const;
bool compare(AbstractDecklistNode *other) const override;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
QVector<QPair<int, int>> sort(Qt::SortOrder order = Qt::AscendingOrder);
bool readElement(QXmlStreamReader *xml) override;
void writeElement(QXmlStreamWriter *xml) override;
};
class AbstractDecklistCardNode : public AbstractDecklistNode
{
public:
explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent)
{
}
virtual int getNumber() const = 0;
virtual void setNumber(int _number) = 0;
QString getName() const override = 0;
virtual void setName(const QString &_name) = 0;
virtual QString getCardUuid() const override = 0;
virtual void setCardSetCode(const QString &_cardSetName) = 0;
virtual QString getCardCollectorNumber() const override = 0;
virtual void setCardCollectorNumber(const QString &_cardSetNumber) = 0;
int height() const override
{
return 0;
}
bool compare(AbstractDecklistNode *other) const override;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
bool readElement(QXmlStreamReader *xml) override;
void writeElement(QXmlStreamWriter *xml) override;
};
class DecklistCardNode : public AbstractDecklistCardNode
{
QString name;
int number;
QString cardSetName;
QString cardSetNumber;
public:
explicit DecklistCardNode(QString _name = QString(),
int _number = 1,
InnerDecklistNode *_parent = nullptr,
QString _cardSetName = QString(),
QString _cardSetNumber = QString())
: AbstractDecklistCardNode(_parent), name(std::move(_name)), number(_number),
cardSetName(std::move(_cardSetName)), cardSetNumber(std::move(_cardSetNumber))
{
qDebug() << "Adding" << name << number << cardSetName << cardSetNumber;
}
explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
int getNumber() const override
{
return number;
}
void setNumber(int _number) override
{
number = _number;
}
QString getName() const override
{
return name;
}
void setName(const QString &_name) override
{
name = _name;
}
QString getCardUuid() const override
{
return cardSetName;
}
void setCardSetCode(const QString &_cardSetName) override
{
cardSetName = _cardSetName;
}
QString getCardCollectorNumber() const override
{
return cardSetNumber;
}
void setCardCollectorNumber(const QString &_cardSetNumber) override
{
cardSetNumber = _cardSetNumber;
}
};
class DeckList : public QObject
{
Q_OBJECT
private:
QString name, comments;
QString deckHash;
QMap<QString, SideboardPlan *> sideboardPlans;
InnerDecklistNode *root;
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
InnerDecklistNode *getZoneObjFromName(const QString &zoneName);
protected:
virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName)
{
return currentZoneName;
};
virtual QString getCompleteCardName(const QString &cardName) const
{
return cardName;
};
signals:
void deckHashChanged();
public slots:
void setName(const QString &_name = QString())
{
name = _name;
}
void setComments(const QString &_comments = QString())
{
comments = _comments;
}
public:
explicit DeckList();
DeckList(const DeckList &other);
explicit DeckList(const QString &nativeString);
~DeckList() override;
QString getName() const
{
return name;
}
QString getComments() const
{
return comments;
}
QList<MoveCard_ToZone> getCurrentSideboardPlan();
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
const QMap<QString, SideboardPlan *> &getSideboardPlans() const
{
return sideboardPlans;
}
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
bool loadFromXml(QXmlStreamReader *xml);
bool loadFromString_Native(const QString &nativeString);
QString writeToString_Native();
bool loadFromFile_Native(QIODevice *device);
bool saveToFile_Native(QIODevice *device);
bool loadFromStream_Plain(QTextStream &stream);
bool loadFromFile_Plain(QIODevice *device);
bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards);
bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false);
QString writeToString_Plain(bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false);
void cleanList();
bool isEmpty() const
{
return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty();
}
QStringList getCardList() const;
int getSideboardSize() const;
QString getDeckHash() const
{
return deckHash;
}
void updateDeckHash();
InnerDecklistNode *getRoot() const
{
return root;
}
DecklistCardNode *addCard(const QString &cardName,
const QString &zoneName,
const QString &cardSetName = QString(),
const QString &cardSetCollectorNumber = QString());
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr);
/**
* Calls a given function object for each card in the deck. It must
* take a InnerDecklistNode* as its first argument and a
* DecklistCardNode* as its second.
*/
template <typename Callback> void forEachCard(Callback &callback) const
{
// Support for this is only possible if the internal structure
// doesn't get more complicated.
for (int i = 0; i < root->size(); i++) {
const InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++) {
const DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j));
callback(node, card);
}
}
}
};
#endif