[DeckList] Refactor and cleanup methods that iterate over nodes (#6407)

* remove helpers

* create getZoneNodes method

* replace direct calls to getRoot and forEachCard

* remove more non-const uses of forEachCard

* make node getter return const lists

* one more usage

* address comment

* address comment again

* fix hash

* fix hashes (for real this time)
This commit is contained in:
RickyRister 2025-12-12 12:37:44 -08:00 committed by GitHub
parent a390c8ada7
commit 2e2682aad4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 125 additions and 202 deletions

View file

@ -523,56 +523,34 @@ void DeckList::cleanList(bool preserveMetadata)
refreshDeckHash();
}
void DeckList::getCardListHelper(InnerDecklistNode *item, QSet<QString> &result)
{
for (int i = 0; i < item->size(); ++i) {
auto *node = dynamic_cast<DecklistCardNode *>(item->at(i));
if (node) {
result.insert(node->getName());
} else {
getCardListHelper(dynamic_cast<InnerDecklistNode *>(item->at(i)), result);
}
}
}
void DeckList::getCardRefListHelper(InnerDecklistNode *item, QList<CardRef> &result)
{
for (int i = 0; i < item->size(); ++i) {
auto *node = dynamic_cast<DecklistCardNode *>(item->at(i));
if (node) {
result.append(node->toCardRef());
} else {
getCardRefListHelper(dynamic_cast<InnerDecklistNode *>(item->at(i)), result);
}
}
}
QStringList DeckList::getCardList() const
{
QSet<QString> result;
getCardListHelper(root, result);
return result.values();
auto nodes = getCardNodes();
QStringList result;
std::transform(nodes.cbegin(), nodes.cend(), std::back_inserter(result), [](auto node) { return node->getName(); });
return result;
}
QList<CardRef> DeckList::getCardRefList() const
{
auto nodes = getCardNodes();
QList<CardRef> result;
getCardRefListHelper(root, result);
std::transform(nodes.cbegin(), nodes.cend(), std::back_inserter(result),
[](auto node) { return node->toCardRef(); });
return result;
}
QList<DecklistCardNode *> DeckList::getCardNodes(const QStringList &restrictToZones) const
QList<const DecklistCardNode *> DeckList::getCardNodes(const QStringList &restrictToZones) const
{
QList<DecklistCardNode *> result;
QList<const DecklistCardNode *> result;
for (auto *node : *root) {
auto *zoneNode = dynamic_cast<InnerDecklistNode *>(node);
if (zoneNode == nullptr) {
continue;
}
if (!restrictToZones.isEmpty() && !restrictToZones.contains(node->getName())) {
auto zoneNodes = getZoneNodes();
for (auto *zoneNode : zoneNodes) {
if (!restrictToZones.isEmpty() && !restrictToZones.contains(zoneNode->getName())) {
continue;
}
for (auto *cardNode : *zoneNode) {
@ -586,20 +564,28 @@ QList<DecklistCardNode *> DeckList::getCardNodes(const QStringList &restrictToZo
return result;
}
QList<const InnerDecklistNode *> DeckList::getZoneNodes() const
{
QList<const InnerDecklistNode *> zones;
for (auto *node : *root) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(node);
if (!currentZone)
continue;
zones.append(currentZone);
}
return zones;
}
int DeckList::getSideboardSize() const
{
int size = 0;
for (int i = 0; i < root->size(); ++i) {
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
if (node->getName() != DECK_ZONE_SIDE) {
continue;
}
auto cards = getCardNodes({DECK_ZONE_SIDE});
for (int j = 0; j < node->size(); j++) {
auto *card = dynamic_cast<DecklistCardNode *>(node->at(j));
size += card->getNumber();
}
int size = 0;
for (auto card : cards) {
size += card->getNumber();
}
return size;
}
@ -665,26 +651,23 @@ bool DeckList::deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNod
return false;
}
static QString computeDeckHash(const InnerDecklistNode *root)
static QString computeDeckHash(const DeckList &deckList)
{
QStringList cardList;
QSet<QString> hashZones, optionalZones;
auto mainDeckNodes = deckList.getCardNodes({DECK_ZONE_MAIN});
auto sideDeckNodes = deckList.getCardNodes({DECK_ZONE_SIDE});
hashZones << DECK_ZONE_MAIN << DECK_ZONE_SIDE; // Zones in deck to be included in hashing process
optionalZones << DECK_ZONE_TOKENS; // Optional zones in deck not included in hashing process
for (int i = 0; i < root->size(); i++) {
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++) {
if (hashZones.contains(node->getName())) // Mainboard or Sideboard
{
auto *card = dynamic_cast<DecklistCardNode *>(node->at(j));
for (int k = 0; k < card->getNumber(); ++k) {
cardList.append((node->getName() == DECK_ZONE_SIDE ? "SB:" : "") + card->getName().toLower());
}
static auto nodesToCardList = [](const QList<const DecklistCardNode *> &nodes, const QString &prefix = {}) {
QStringList result;
for (auto node : nodes) {
for (int i = 0; i < node->getNumber(); ++i) {
result.append(prefix + node->getName().toLower());
}
}
}
return result;
};
QStringList cardList = nodesToCardList(mainDeckNodes) + nodesToCardList(sideDeckNodes, "SB:");
cardList.sort();
QByteArray deckHashArray = QCryptographicHash::hash(cardList.join(";").toUtf8(), QCryptographicHash::Sha1);
quint64 number = (((quint64)(unsigned char)deckHashArray[0]) << 32) +
@ -706,7 +689,7 @@ QString DeckList::getDeckHash() const
return cachedDeckHash;
}
cachedDeckHash = computeDeckHash(root);
cachedDeckHash = computeDeckHash(*this);
return cachedDeckHash;
}

View file

@ -148,8 +148,6 @@ private:
mutable QString cachedDeckHash;
// Helpers for traversing the tree
static void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result);
static void getCardRefListHelper(InnerDecklistNode *item, QList<CardRef> &result);
InnerDecklistNode *getZoneObjFromName(const QString &zoneName);
public:
@ -267,7 +265,8 @@ public:
}
QStringList getCardList() const;
QList<CardRef> getCardRefList() const;
QList<DecklistCardNode *> getCardNodes(const QStringList &restrictToZones = QStringList()) const;
QList<const DecklistCardNode *> getCardNodes(const QStringList &restrictToZones = QStringList()) const;
QList<const InnerDecklistNode *> getZoneNodes() const;
int getSideboardSize() const;
InnerDecklistNode *getRoot() const
{