[DeckListModel] optimize by iterating over cardNodes instead of ExactCards (#6485)

* [DeckListModel] optimize by iterating over cardNodes instead of ExactCards

* fix build failure

* another optimization

* fix build failure
This commit is contained in:
RickyRister 2026-01-03 19:19:04 -08:00 committed by GitHub
parent f16c552d97
commit 746f2af044
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 67 additions and 76 deletions

View file

@ -2,6 +2,7 @@
#include "card_group_display_widgets/flat_card_group_display_widget.h" #include "card_group_display_widgets/flat_card_group_display_widget.h"
#include "card_group_display_widgets/overlapped_card_group_display_widget.h" #include "card_group_display_widgets/overlapped_card_group_display_widget.h"
#include "libcockatrice/card/database/card_database_manager.h"
#include <QResizeEvent> #include <QResizeEvent>
#include <libcockatrice/models/deck_list/deck_list_model.h> #include <libcockatrice/models/deck_list/deck_list_model.h>
@ -230,10 +231,13 @@ QList<QString> DeckCardZoneDisplayWidget::getGroupCriteriaValueList()
{ {
QList<QString> groupCriteriaValues; QList<QString> groupCriteriaValues;
QList<ExactCard> cardsInZone = deckListModel->getCardsForZone(zoneName); QList<const DecklistCardNode *> nodes = deckListModel->getCardNodesForZone(zoneName);
for (const ExactCard &cardInZone : cardsInZone) { for (auto node : nodes) {
groupCriteriaValues.append(cardInZone.getInfo().getProperty(activeGroupCriteria)); CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(node->getName());
if (info) {
groupCriteriaValues.append(info->getProperty(activeGroupCriteria));
}
} }
groupCriteriaValues.removeDuplicates(); groupCriteriaValues.removeDuplicates();

View file

@ -170,7 +170,7 @@ void DrawProbabilityWidget::updateFilterOptions()
const auto nodes = analyzer->getModel()->getCardNodes(); const auto nodes = analyzer->getModel()->getCardNodes();
for (auto *node : nodes) { for (auto *node : nodes) {
CardInfoPtr info = CardDatabaseManager::query()->getCard({node->getName()}).getCardPtr(); CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(node->getName());
if (!info) { if (!info) {
continue; continue;
} }

View file

@ -19,82 +19,91 @@ void DeckListStatisticsAnalyzer::analyze()
{ {
clearData(); clearData();
QList<ExactCard> cards = model->getCards(); QList<const DecklistCardNode *> nodes = model->getCardNodes();
for (auto card : cards) { for (auto node : nodes) {
auto info = card.getInfo(); CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(node->getName());
const int cmc = info.getCmc().toInt(); if (!info) {
continue;
}
const int amount = node->getNumber();
QStringList copiesOfName;
for (int i = 0; i < amount; i++) {
copiesOfName.append(node->getName());
}
// Convert once // Convert once
QStringList types = info.getMainCardType().split(' '); const int cmc = info->getCmc().toInt();
QStringList subtypes = info.getCardType().split('-').last().split(" "); QStringList types = info->getMainCardType().split(' ');
QString colors = info.getColors(); QStringList subtypes = info->getCardType().split('-').last().split(" ");
int power = info.getPowTough().split("/").first().toInt(); QString colors = info->getColors();
int toughness = info.getPowTough().split("/").last().toInt(); int power = info->getPowTough().split("/").first().toInt();
int toughness = info->getPowTough().split("/").last().toInt();
// For each copy of card // For each copy of card
// ---------------- Mana Curve ---------------- // ---------------- Mana Curve ----------------
if (config.computeManaCurve) { if (config.computeManaCurve) {
manaCurveMap[cmc]++; manaCurveMap[cmc] += amount;
} }
// per-type curve // per-type curve
for (auto &t : types) { for (auto &t : types) {
manaCurveByType[t][cmc]++; manaCurveByType[t][cmc] += amount;
manaCurveCardsByType[t][cmc].append(info.getName()); manaCurveCardsByType[t][cmc] << copiesOfName;
} }
// Per-subtype curve // Per-subtype curve
for (auto &st : subtypes) { for (auto &st : subtypes) {
manaCurveBySubtype[st][cmc]++; manaCurveBySubtype[st][cmc] += amount;
manaCurveCardsBySubtype[st][cmc].append(info.getName()); manaCurveCardsBySubtype[st][cmc] << copiesOfName;
} }
// per-color curve // per-color curve
for (auto &c : colors) { for (auto &c : colors) {
manaCurveByColor[c][cmc]++; manaCurveByColor[c][cmc] += amount;
manaCurveCardsByColor[c][cmc].append(info.getName()); manaCurveCardsByColor[c][cmc] << copiesOfName;
} }
// Power/toughness // Power/toughness
manaCurveByPower[QString::number(power)][cmc]++; manaCurveByPower[QString::number(power)][cmc] += amount;
manaCurveCardsByPower[QString::number(power)][cmc].append(info.getName()); manaCurveCardsByPower[QString::number(power)][cmc] << copiesOfName;
manaCurveByToughness[QString::number(toughness)][cmc]++; manaCurveByToughness[QString::number(toughness)][cmc] += amount;
manaCurveCardsByToughness[QString::number(toughness)][cmc].append(info.getName()); manaCurveCardsByToughness[QString::number(toughness)][cmc] << copiesOfName;
// ========== Category Counts =========== // ========== Category Counts ===========
for (auto &t : types) { for (auto &t : types) {
typeCount[t]++; typeCount[t] += amount;
} }
for (auto &st : subtypes) { for (auto &st : subtypes) {
subtypeCount[st]++; subtypeCount[st] += amount;
} }
for (auto &c : colors) { for (auto &c : colors) {
colorCount[c]++; colorCount[c] += amount;
} }
manaValueCount[cmc]++; manaValueCount[cmc] += amount;
// ---------------- Mana Base ---------------- // ---------------- Mana Base ----------------
if (config.computeManaBase) { if (config.computeManaBase) {
auto prod = determineManaProduction(info.getText()); auto prod = determineManaProduction(info->getText());
for (auto it = prod.begin(); it != prod.end(); ++it) { for (auto it = prod.begin(); it != prod.end(); ++it) {
if (it.value() > 0) { if (it.value() > 0) {
productionPipCount[it.key()] += it.value(); productionPipCount[it.key()] += it.value() * amount;
productionCardCount[it.key()]++; productionCardCount[it.key()] += amount;
} }
manaBaseMap[it.key()] += it.value(); manaBaseMap[it.key()] += it.value() * amount;
} }
} }
// ---------------- Devotion ---------------- // ---------------- Devotion ----------------
if (config.computeDevotion) { if (config.computeDevotion) {
auto devo = countManaSymbols(info.getManaCost()); auto devo = countManaSymbols(info->getManaCost());
for (auto &d : devo) { for (auto &d : devo) {
if (d.second > 0) { if (d.second > 0) {
devotionPipCount[QString(d.first)] += d.second; devotionPipCount[QString(d.first)] += d.second * amount;
devotionCardCount[QString(d.first)]++; devotionCardCount[QString(d.first)] += amount;
} }
manaDevotionMap[d.first] += d.second; manaDevotionMap[d.first] += d.second * amount;
} }
} }
} }

View file

@ -81,13 +81,30 @@ void VisualDeckEditorSampleHandWidget::updateDisplay()
} }
} }
static QList<ExactCard> cardNodesToExactCards(QList<const DecklistCardNode *> nodes)
{
QList<ExactCard> cards;
for (auto node : nodes) {
ExactCard card = CardDatabaseManager::query()->getCard(node->toCardRef());
if (card) {
for (int k = 0; k < node->getNumber(); ++k) {
cards.append(card);
}
} else {
qDebug() << "Card not found in database!";
}
}
return cards;
}
QList<ExactCard> VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGet) QList<ExactCard> VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGet)
{ {
QList<ExactCard> randomCards; QList<ExactCard> randomCards;
if (!deckListModel) if (!deckListModel)
return randomCards; return randomCards;
QList<ExactCard> mainDeckCards = deckListModel->getCardsForZone(DECK_ZONE_MAIN); QList<ExactCard> mainDeckCards = cardNodesToExactCards(deckListModel->getCardNodesForZone(DECK_ZONE_MAIN));
if (mainDeckCards.isEmpty()) if (mainDeckCards.isEmpty())
return randomCards; return randomCards;

View file

@ -608,35 +608,6 @@ void DeckListModel::forEachCard(const std::function<void(InnerDecklistNode *, De
deckList->forEachCard(func); deckList->forEachCard(func);
} }
static QList<ExactCard> cardNodesToExactCards(QList<const DecklistCardNode *> nodes)
{
QList<ExactCard> cards;
for (auto node : nodes) {
ExactCard card = CardDatabaseManager::query()->getCard(node->toCardRef());
if (card) {
for (int k = 0; k < node->getNumber(); ++k) {
cards.append(card);
}
} else {
qDebug() << "Card not found in database!";
}
}
return cards;
}
QList<ExactCard> DeckListModel::getCards() const
{
auto nodes = deckList->getCardNodes();
return cardNodesToExactCards(nodes);
}
QList<ExactCard> DeckListModel::getCardsForZone(const QString &zoneName) const
{
auto nodes = deckList->getCardNodes({zoneName});
return cardNodesToExactCards(nodes);
}
QList<const DecklistCardNode *> DeckListModel::getCardNodes() const QList<const DecklistCardNode *> DeckListModel::getCardNodes() const
{ {
return deckList->getCardNodes(); return deckList->getCardNodes();

View file

@ -329,16 +329,6 @@ public:
*/ */
void forEachCard(const std::function<void(InnerDecklistNode *, DecklistCardNode *)> &func); void forEachCard(const std::function<void(InnerDecklistNode *, DecklistCardNode *)> &func);
/**
* @brief Creates a list consisting of the entries of the model mapped into ExactCards (with each entry looked up
* in the card database).
* If a card node has number > 1, it will be added that many times to the list.
* If an entry's card is not found in the card database, that entry will be left out of the list.
* @return An ordered list of ExactCards
*/
[[nodiscard]] QList<ExactCard> getCards() const;
[[nodiscard]] QList<ExactCard> getCardsForZone(const QString &zoneName) const;
/** /**
* @brief Gets a list of all card nodes in the deck. * @brief Gets a list of all card nodes in the deck.
*/ */