[VDE] Consolidate statistical analysis into a separate object (#6392)

* [VDE] Consolidate statistical analysis into a separate object so multiple widgets can re-use calculations and calculation is only performed once on data change.

* [VDE] Lint.

* [VDE] Move struct up to not confuse compiler.

* [VDE] NoDiscards

* [VDE] Move variables

* [VDE] Lint.
This commit is contained in:
BruebachL
2025-12-02 13:51:08 +01:00
committed by GitHub
parent 364d0ca52b
commit f0ebd28148
12 changed files with 215 additions and 202 deletions

View File

@@ -142,6 +142,7 @@ set(cockatrice_SOURCES
src/interface/widgets/cards/deck_card_zone_display_widget.cpp src/interface/widgets/cards/deck_card_zone_display_widget.cpp
src/interface/widgets/cards/deck_preview_card_picture_widget.cpp src/interface/widgets/cards/deck_preview_card_picture_widget.cpp
src/interface/widgets/deck_analytics/deck_analytics_widget.cpp src/interface/widgets/deck_analytics/deck_analytics_widget.cpp
src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp
src/interface/widgets/deck_analytics/mana_base_widget.cpp src/interface/widgets/deck_analytics/mana_base_widget.cpp
src/interface/widgets/deck_analytics/mana_curve_widget.cpp src/interface/widgets/deck_analytics/mana_curve_widget.cpp
src/interface/widgets/deck_analytics/mana_devotion_widget.cpp src/interface/widgets/deck_analytics/mana_devotion_widget.cpp

View File

@@ -17,20 +17,19 @@ DeckAnalyticsWidget::DeckAnalyticsWidget(QWidget *parent, DeckListModel *_deckLi
container->setLayout(containerLayout); container->setLayout(containerLayout);
scrollArea->setWidget(container); scrollArea->setWidget(container);
manaCurveWidget = new ManaCurveWidget(this, deckListModel); deckListStatisticsAnalyzer = new DeckListStatisticsAnalyzer(this, deckListModel);
manaCurveWidget = new ManaCurveWidget(this, deckListStatisticsAnalyzer);
containerLayout->addWidget(manaCurveWidget); containerLayout->addWidget(manaCurveWidget);
manaDevotionWidget = new ManaDevotionWidget(this, deckListModel); manaDevotionWidget = new ManaDevotionWidget(this, deckListStatisticsAnalyzer);
containerLayout->addWidget(manaDevotionWidget); containerLayout->addWidget(manaDevotionWidget);
manaBaseWidget = new ManaBaseWidget(this, deckListModel); manaBaseWidget = new ManaBaseWidget(this, deckListStatisticsAnalyzer);
containerLayout->addWidget(manaBaseWidget); containerLayout->addWidget(manaBaseWidget);
} }
void DeckAnalyticsWidget::refreshDisplays(DeckListModel *_deckModel) void DeckAnalyticsWidget::refreshDisplays()
{ {
deckListModel = _deckModel; deckListStatisticsAnalyzer->update();
manaCurveWidget->setDeckModel(_deckModel);
manaDevotionWidget->setDeckModel(_deckModel);
manaBaseWidget->setDeckModel(_deckModel);
} }

View File

@@ -24,10 +24,11 @@ public:
explicit DeckAnalyticsWidget(QWidget *parent, DeckListModel *deckListModel); explicit DeckAnalyticsWidget(QWidget *parent, DeckListModel *deckListModel);
void setDeckList(const DeckList &_deckListModel); void setDeckList(const DeckList &_deckListModel);
std::map<int, int> analyzeManaCurve(); std::map<int, int> analyzeManaCurve();
void refreshDisplays(DeckListModel *_deckListModel); void refreshDisplays();
private: private:
DeckListModel *deckListModel; DeckListModel *deckListModel;
DeckListStatisticsAnalyzer *deckListStatisticsAnalyzer;
QVBoxLayout *mainLayout; QVBoxLayout *mainLayout;
QWidget *container; QWidget *container;

View File

@@ -0,0 +1,120 @@
#include "deck_list_statistics_analyzer.h"
#include "deck_list_model.h"
#include "deck_list_statistics_analyzer.h"
#include <QRegularExpression>
#include <libcockatrice/card/database/card_database_manager.h>
#include <libcockatrice/deck_list/deck_list.h>
DeckListStatisticsAnalyzer::DeckListStatisticsAnalyzer(QObject *parent,
DeckListModel *_model,
DeckListStatisticsAnalyzerConfig cfg)
: QObject(parent), model(_model), config(cfg)
{
connect(model, &DeckListModel::dataChanged, this, &DeckListStatisticsAnalyzer::update);
}
void DeckListStatisticsAnalyzer::update()
{
manaBaseMap.clear();
manaCurveMap.clear();
manaDevotionMap.clear();
auto nodes = model->getDeckList()->getCardNodes();
for (auto *node : nodes) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(node->getName());
if (!info)
continue;
for (int i = 0; i < node->getNumber(); ++i) {
// ---- Mana curve ----
if (config.computeManaCurve) {
manaCurveMap[info->getCmc().toInt()]++;
}
// ---- Mana base ----
if (config.computeManaBase) {
auto mana = determineManaProduction(info->getText());
for (auto it = mana.begin(); it != mana.end(); ++it)
manaBaseMap[it.key()] += it.value();
}
// ---- Devotion ----
if (config.computeDevotion) {
auto devo = countManaSymbols(info->getManaCost());
for (auto &d : devo)
manaDevotionMap[d.first] += d.second;
}
}
}
emit statsUpdated();
}
QHash<QString, int> DeckListStatisticsAnalyzer::determineManaProduction(const QString &rulesText)
{
QHash<QString, int> manaCounts = {{"W", 0}, {"U", 0}, {"B", 0}, {"R", 0}, {"G", 0}, {"C", 0}};
QString text = rulesText.toLower(); // Normalize case for matching
// Quick keyword-based checks for any color and colorless mana
if (text.contains("{t}: add one mana of any color") || text.contains("add one mana of any color")) {
for (const auto &color : {QStringLiteral("W"), QStringLiteral("U"), QStringLiteral("B"), QStringLiteral("R"),
QStringLiteral("G")}) {
manaCounts[color]++;
}
}
if (text.contains("{t}: add {c}") || text.contains("add one colorless mana")) {
manaCounts["C"]++;
}
// Optimized regex for specific mana symbols
static const QRegularExpression specificColorRegex(R"(\{T\}:\s*Add\s*\{([WUBRG])\})");
QRegularExpressionMatch match = specificColorRegex.match(rulesText);
if (match.hasMatch()) {
manaCounts[match.captured(1)]++;
}
return manaCounts;
}
std::unordered_map<char, int> DeckListStatisticsAnalyzer::countManaSymbols(const QString &manaString)
{
std::unordered_map<char, int> manaCounts = {{'W', 0}, {'U', 0}, {'B', 0}, {'R', 0}, {'G', 0}};
int len = manaString.length();
for (int i = 0; i < len; ++i) {
if (manaString[i] == '{') {
++i; // Move past '{'
if (i < len && manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) {
char mana1 = manaString[i].toLatin1();
++i; // Move to next character
if (i < len && manaString[i] == '/') {
++i; // Move past '/'
if (i < len && manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) {
char mana2 = manaString[i].toLatin1();
manaCounts[mana1]++;
manaCounts[mana2]++;
} else {
// Handle cases like "{W/}" where second part is invalid
manaCounts[mana1]++;
}
} else {
manaCounts[mana1]++;
}
}
// Ensure we always skip to the closing '}'
while (i < len && manaString[i] != '}') {
++i;
}
}
// Check if the character is a standalone mana symbol (not inside {})
else if (manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) {
manaCounts[manaString[i].toLatin1()]++;
}
}
return manaCounts;
}

View File

@@ -0,0 +1,60 @@
#ifndef COCKATRICE_DECK_LIST_STATISTICS_ANALYZER_H
#define COCKATRICE_DECK_LIST_STATISTICS_ANALYZER_H
#include "deck_list_model.h"
#include <QHash>
#include <QObject>
#include <unordered_map>
class DeckListModel;
struct DeckListStatisticsAnalyzerConfig
{
bool computeManaBase = true;
bool computeManaCurve = true;
bool computeDevotion = true;
};
class DeckListStatisticsAnalyzer : public QObject
{
Q_OBJECT
public:
explicit DeckListStatisticsAnalyzer(QObject *parent,
DeckListModel *model,
DeckListStatisticsAnalyzerConfig cfg = DeckListStatisticsAnalyzerConfig());
void update();
[[nodiscard]] const QHash<QString, int> &getManaBase() const
{
return manaBaseMap;
}
[[nodiscard]] const std::unordered_map<int, int> &getManaCurve() const
{
return manaCurveMap;
}
[[nodiscard]] const std::unordered_map<char, int> &getDevotion() const
{
return manaDevotionMap;
}
signals:
void statsUpdated();
private:
DeckListModel *model;
DeckListStatisticsAnalyzerConfig config;
// Internal result containers
QHash<QString, int> manaBaseMap;
std::unordered_map<int, int> manaCurveMap;
std::unordered_map<char, int> manaDevotionMap;
// Internal helper functions
QHash<QString, int> determineManaProduction(const QString &);
std::unordered_map<char, int> countManaSymbols(const QString &);
};
#endif // COCKATRICE_DECK_LIST_STATISTICS_ANALYZER_H

View File

@@ -10,8 +10,8 @@
#include <libcockatrice/card/database/card_database_manager.h> #include <libcockatrice/card/database/card_database_manager.h>
#include <libcockatrice/deck_list/deck_list.h> #include <libcockatrice/deck_list/deck_list.h>
ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *_deckListModel) ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListStatisticsAnalyzer *_deckStatAnalyzer)
: QWidget(parent), deckListModel(_deckListModel) : QWidget(parent), deckStatAnalyzer(_deckStatAnalyzer)
{ {
layout = new QVBoxLayout(this); layout = new QVBoxLayout(this);
setLayout(layout); setLayout(layout);
@@ -24,7 +24,7 @@ ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *_deckListModel)
barLayout = new QHBoxLayout(barContainer); barLayout = new QHBoxLayout(barContainer);
layout->addWidget(barContainer); layout->addWidget(barContainer);
connect(deckListModel, &DeckListModel::dataChanged, this, &ManaBaseWidget::analyzeManaBase); connect(deckStatAnalyzer, &DeckListStatisticsAnalyzer::statsUpdated, this, &ManaBaseWidget::updateDisplay);
retranslateUi(); retranslateUi();
} }
@@ -34,13 +34,6 @@ void ManaBaseWidget::retranslateUi()
bannerWidget->setText(tr("Mana Base")); bannerWidget->setText(tr("Mana Base"));
} }
void ManaBaseWidget::setDeckModel(DeckListModel *deckModel)
{
deckListModel = deckModel;
connect(deckListModel, &DeckListModel::dataChanged, this, &ManaBaseWidget::analyzeManaBase);
analyzeManaBase();
}
void ManaBaseWidget::updateDisplay() void ManaBaseWidget::updateDisplay()
{ {
// Clear the layout first // Clear the layout first
@@ -50,6 +43,8 @@ void ManaBaseWidget::updateDisplay()
delete item; delete item;
} }
auto manaBaseMap = deckStatAnalyzer->getManaBase();
int highestEntry = 0; int highestEntry = 0;
for (auto entry : manaBaseMap) { for (auto entry : manaBaseMap) {
if (entry > highestEntry) { if (entry > highestEntry) {
@@ -74,56 +69,3 @@ void ManaBaseWidget::updateDisplay()
update(); update();
} }
QHash<QString, int> ManaBaseWidget::analyzeManaBase()
{
manaBaseMap.clear();
QList<DecklistCardNode *> cardsInDeck = deckListModel->getDeckList()->getCardNodes();
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
auto devotion = determineManaProduction(info->getText());
mergeManaCounts(manaBaseMap, devotion);
}
}
}
updateDisplay();
return manaBaseMap;
}
QHash<QString, int> ManaBaseWidget::determineManaProduction(const QString &rulesText)
{
QHash<QString, int> manaCounts = {{"W", 0}, {"U", 0}, {"B", 0}, {"R", 0}, {"G", 0}, {"C", 0}};
QString text = rulesText.toLower(); // Normalize case for matching
// Quick keyword-based checks for any color and colorless mana
if (text.contains("{t}: add one mana of any color") || text.contains("add one mana of any color")) {
for (const auto &color : {QStringLiteral("W"), QStringLiteral("U"), QStringLiteral("B"), QStringLiteral("R"),
QStringLiteral("G")}) {
manaCounts[color]++;
}
}
if (text.contains("{t}: add {c}") || text.contains("add one colorless mana")) {
manaCounts["C"]++;
}
// Optimized regex for specific mana symbols
static const QRegularExpression specificColorRegex(R"(\{T\}:\s*Add\s*\{([WUBRG])\})");
QRegularExpressionMatch match = specificColorRegex.match(rulesText);
if (match.hasMatch()) {
manaCounts[match.captured(1)]++;
}
return manaCounts;
}
void ManaBaseWidget::mergeManaCounts(QHash<QString, int> &manaCounts1, const QHash<QString, int> &manaCounts2)
{
for (auto it = manaCounts2.constBegin(); it != manaCounts2.constEnd(); ++it) {
manaCounts1[it.key()] += it.value();
}
}

View File

@@ -8,6 +8,7 @@
#define MANA_BASE_WIDGET_H #define MANA_BASE_WIDGET_H
#include "../general/display/banner_widget.h" #include "../general/display/banner_widget.h"
#include "deck_list_statistics_analyzer.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QWidget> #include <QWidget>
@@ -20,21 +21,15 @@ class ManaBaseWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit ManaBaseWidget(QWidget *parent, DeckListModel *deckListModel); explicit ManaBaseWidget(QWidget *parent, DeckListStatisticsAnalyzer *deckStatAnalyzer);
QHash<QString, int> analyzeManaBase();
void updateDisplay(); void updateDisplay();
QHash<QString, int> determineManaProduction(const QString &manaString);
void mergeManaCounts(QHash<QString, int> &manaCounts1, const QHash<QString, int> &manaCounts2);
public slots: public slots:
void setDeckModel(DeckListModel *deckModel);
void retranslateUi(); void retranslateUi();
private: private:
DeckListModel *deckListModel; DeckListStatisticsAnalyzer *deckStatAnalyzer;
BannerWidget *bannerWidget; BannerWidget *bannerWidget;
QHash<QString, int> manaBaseMap;
QVBoxLayout *layout; QVBoxLayout *layout;
QWidget *barContainer; QWidget *barContainer;
QHBoxLayout *barLayout; QHBoxLayout *barLayout;

View File

@@ -10,8 +10,8 @@
#include <libcockatrice/deck_list/deck_list.h> #include <libcockatrice/deck_list/deck_list.h>
#include <unordered_map> #include <unordered_map>
ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListModel *_deckListModel) ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListStatisticsAnalyzer *_deckStatAnalyzer)
: QWidget(parent), deckListModel(_deckListModel) : QWidget(parent), deckStatAnalyzer(_deckStatAnalyzer)
{ {
layout = new QVBoxLayout(this); layout = new QVBoxLayout(this);
setLayout(layout); setLayout(layout);
@@ -24,7 +24,7 @@ ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListModel *_deckListModel)
barLayout = new QHBoxLayout(barContainer); barLayout = new QHBoxLayout(barContainer);
layout->addWidget(barContainer); layout->addWidget(barContainer);
connect(deckListModel, &DeckListModel::dataChanged, this, &ManaCurveWidget::analyzeManaCurve); connect(deckStatAnalyzer, &DeckListStatisticsAnalyzer::statsUpdated, this, &ManaCurveWidget::updateDisplay);
retranslateUi(); retranslateUi();
} }
@@ -34,34 +34,6 @@ void ManaCurveWidget::retranslateUi()
bannerWidget->setText(tr("Mana Curve")); bannerWidget->setText(tr("Mana Curve"));
} }
void ManaCurveWidget::setDeckModel(DeckListModel *deckModel)
{
deckListModel = deckModel;
connect(deckListModel, &DeckListModel::dataChanged, this, &ManaCurveWidget::analyzeManaCurve);
analyzeManaCurve();
}
std::unordered_map<int, int> ManaCurveWidget::analyzeManaCurve()
{
manaCurveMap.clear();
QList<DecklistCardNode *> cardsInDeck = deckListModel->getDeckList()->getCardNodes();
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
int cmc = info->getCmc().toInt();
manaCurveMap[cmc]++;
}
}
}
updateDisplay();
return manaCurveMap;
}
void ManaCurveWidget::updateDisplay() void ManaCurveWidget::updateDisplay()
{ {
// Clear the layout first // Clear the layout first
@@ -73,6 +45,8 @@ void ManaCurveWidget::updateDisplay()
} }
} }
auto manaCurveMap = deckStatAnalyzer->getManaCurve();
int highestEntry = 0; int highestEntry = 0;
for (const auto &entry : manaCurveMap) { for (const auto &entry : manaCurveMap) {
if (entry.second > highestEntry) { if (entry.second > highestEntry) {

View File

@@ -8,6 +8,7 @@
#define MANA_CURVE_WIDGET_H #define MANA_CURVE_WIDGET_H
#include "../general/display/banner_widget.h" #include "../general/display/banner_widget.h"
#include "deck_list_statistics_analyzer.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QWidget> #include <QWidget>
@@ -19,17 +20,14 @@ class ManaCurveWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit ManaCurveWidget(QWidget *parent, DeckListModel *deckListModel); explicit ManaCurveWidget(QWidget *parent, DeckListStatisticsAnalyzer *deckStatAnalyzer);
void updateDisplay(); void updateDisplay();
public slots: public slots:
void setDeckModel(DeckListModel *deckModel);
std::unordered_map<int, int> analyzeManaCurve();
void retranslateUi(); void retranslateUi();
private: private:
DeckListModel *deckListModel; DeckListStatisticsAnalyzer *deckStatAnalyzer;
std::unordered_map<int, int> manaCurveMap;
QVBoxLayout *layout; QVBoxLayout *layout;
BannerWidget *bannerWidget; BannerWidget *bannerWidget;
QWidget *barContainer; QWidget *barContainer;

View File

@@ -10,8 +10,8 @@
#include <regex> #include <regex>
#include <unordered_map> #include <unordered_map>
ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListModel *_deckListModel) ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListStatisticsAnalyzer *_deckStatAnalyzer)
: QWidget(parent), deckListModel(_deckListModel) : QWidget(parent), deckStatAnalyzer(_deckStatAnalyzer)
{ {
layout = new QVBoxLayout(this); layout = new QVBoxLayout(this);
setLayout(layout); setLayout(layout);
@@ -23,7 +23,7 @@ ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListModel *_deckList
barLayout = new QHBoxLayout(); barLayout = new QHBoxLayout();
layout->addLayout(barLayout); layout->addLayout(barLayout);
connect(deckListModel, &DeckListModel::dataChanged, this, &ManaDevotionWidget::analyzeManaDevotion); connect(deckStatAnalyzer, &DeckListStatisticsAnalyzer::statsUpdated, this, &ManaDevotionWidget::updateDisplay);
retranslateUi(); retranslateUi();
} }
@@ -33,33 +33,6 @@ void ManaDevotionWidget::retranslateUi()
bannerWidget->setText(tr("Mana Devotion")); bannerWidget->setText(tr("Mana Devotion"));
} }
void ManaDevotionWidget::setDeckModel(DeckListModel *deckModel)
{
deckListModel = deckModel;
connect(deckListModel, &DeckListModel::dataChanged, this, &ManaDevotionWidget::analyzeManaDevotion);
analyzeManaDevotion();
}
std::unordered_map<char, int> ManaDevotionWidget::analyzeManaDevotion()
{
manaDevotionMap.clear();
QList<DecklistCardNode *> cardsInDeck = deckListModel->getDeckList()->getCardNodes();
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
auto devotion = countManaSymbols(info->getManaCost());
mergeManaCounts(manaDevotionMap, devotion);
}
}
}
updateDisplay();
return manaDevotionMap;
}
void ManaDevotionWidget::updateDisplay() void ManaDevotionWidget::updateDisplay()
{ {
// Clear the layout first // Clear the layout first
@@ -69,6 +42,8 @@ void ManaDevotionWidget::updateDisplay()
delete item; delete item;
} }
auto manaDevotionMap = deckStatAnalyzer->getDevotion();
int highestEntry = 0; int highestEntry = 0;
for (auto entry : manaDevotionMap) { for (auto entry : manaDevotionMap) {
if (highestEntry < entry.second) { if (highestEntry < entry.second) {
@@ -89,50 +64,3 @@ void ManaDevotionWidget::updateDisplay()
update(); // Update the widget display update(); // Update the widget display
} }
std::unordered_map<char, int> ManaDevotionWidget::countManaSymbols(const QString &manaString)
{
std::unordered_map<char, int> manaCounts = {{'W', 0}, {'U', 0}, {'B', 0}, {'R', 0}, {'G', 0}};
int len = manaString.length();
for (int i = 0; i < len; ++i) {
if (manaString[i] == '{') {
++i; // Move past '{'
if (i < len && manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) {
char mana1 = manaString[i].toLatin1();
++i; // Move to next character
if (i < len && manaString[i] == '/') {
++i; // Move past '/'
if (i < len && manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) {
char mana2 = manaString[i].toLatin1();
manaCounts[mana1]++;
manaCounts[mana2]++;
} else {
// Handle cases like "{W/}" where second part is invalid
manaCounts[mana1]++;
}
} else {
manaCounts[mana1]++;
}
}
// Ensure we always skip to the closing '}'
while (i < len && manaString[i] != '}') {
++i;
}
}
// Check if the character is a standalone mana symbol (not inside {})
else if (manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) {
manaCounts[manaString[i].toLatin1()]++;
}
}
return manaCounts;
}
void ManaDevotionWidget::mergeManaCounts(std::unordered_map<char, int> &manaCounts1,
const std::unordered_map<char, int> &manaCounts2)
{
for (const auto &pair : manaCounts2) {
manaCounts1[pair.first] += pair.second; // Add values for matching keys
}
}

View File

@@ -8,6 +8,7 @@
#define MANA_DEVOTION_WIDGET_H #define MANA_DEVOTION_WIDGET_H
#include "../general/display/banner_widget.h" #include "../general/display/banner_widget.h"
#include "deck_list_statistics_analyzer.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QWidget> #include <QWidget>
@@ -20,21 +21,15 @@ class ManaDevotionWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit ManaDevotionWidget(QWidget *parent, DeckListModel *deckListModel); explicit ManaDevotionWidget(QWidget *parent, DeckListStatisticsAnalyzer *deckStatAnalyzer);
void updateDisplay(); void updateDisplay();
std::unordered_map<char, int> countManaSymbols(const QString &manaString);
void mergeManaCounts(std::unordered_map<char, int> &manaCounts1, const std::unordered_map<char, int> &manaCounts2);
public slots: public slots:
void setDeckModel(DeckListModel *deckModel);
std::unordered_map<char, int> analyzeManaDevotion();
void retranslateUi(); void retranslateUi();
private: private:
DeckListModel *deckListModel; DeckListStatisticsAnalyzer *deckStatAnalyzer;
BannerWidget *bannerWidget; BannerWidget *bannerWidget;
std::unordered_map<char, int> manaDevotionMap;
QVBoxLayout *layout; QVBoxLayout *layout;
QHBoxLayout *barLayout; QHBoxLayout *barLayout;
}; };

View File

@@ -84,7 +84,7 @@ void TabDeckEditorVisual::onDeckChanged()
{ {
AbstractTabDeckEditor::onDeckModified(); AbstractTabDeckEditor::onDeckModified();
tabContainer->visualDeckView->constructZoneWidgetsFromDeckListModel(); tabContainer->visualDeckView->constructZoneWidgetsFromDeckListModel();
tabContainer->deckAnalytics->refreshDisplays(deckDockWidget->deckModel); tabContainer->deckAnalytics->refreshDisplays();
tabContainer->sampleHandWidget->setDeckModel(deckDockWidget->deckModel); tabContainer->sampleHandWidget->setDeckModel(deckDockWidget->deckModel);
} }