mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-04 12:33:55 -07:00
[Game] Refactor subtype tally code to be more generic
This commit is contained in:
parent
055ba9a16f
commit
37fd1499c3
8 changed files with 140 additions and 80 deletions
|
|
@ -83,7 +83,6 @@ set(cockatrice_SOURCES
|
|||
src/game/game_state.cpp
|
||||
src/game_graphics/game_view.cpp
|
||||
src/game_graphics/hand_counter.cpp
|
||||
src/game/selection_subtype_tally.cpp
|
||||
src/game_graphics/log/message_log_widget.cpp
|
||||
src/game/phase.cpp
|
||||
src/game_graphics/phases_toolbar.cpp
|
||||
|
|
@ -99,6 +98,8 @@ set(cockatrice_SOURCES
|
|||
src/game_graphics/player/menu/say_menu.cpp
|
||||
src/game_graphics/player/menu/sideboard_menu.cpp
|
||||
src/game_graphics/player/menu/utility_menu.cpp
|
||||
src/game_graphics/tally/subtype_tally.cpp
|
||||
src/game_graphics/tally/tally.cpp
|
||||
src/game/player/player_actions.cpp
|
||||
src/game_graphics/player/player_area.cpp
|
||||
src/game_graphics/player/player_dialogs.cpp
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
#ifndef SELECTION_SUBTYPE_TALLY_H
|
||||
#define SELECTION_SUBTYPE_TALLY_H
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
class CardItem;
|
||||
|
||||
/** @brief A single subtype (e.g., "Goblin", "Warrior") with its occurrence count. */
|
||||
struct SubtypeEntry
|
||||
{
|
||||
QString name; ///< The subtype name
|
||||
int count; ///< Number of selected cards with this subtype
|
||||
|
||||
bool operator==(const SubtypeEntry &other) const
|
||||
{
|
||||
return name == other.name && count == other.count;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Extracts and tallies subtypes from selected cards.
|
||||
*/
|
||||
namespace SelectionSubtypeTally
|
||||
{
|
||||
/**
|
||||
* @brief Parses card type lines and counts each subtype occurrence.
|
||||
*
|
||||
* Skips face-down cards and cards without type info.
|
||||
* @param cards The list of selected card items to analyze.
|
||||
* @return Entries sorted by count ascending, then alphabetically.
|
||||
*/
|
||||
QList<SubtypeEntry> countSubtypes(const QList<CardItem *> &cards);
|
||||
} // namespace SelectionSubtypeTally
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#include "game_view.h"
|
||||
|
||||
#include "../client/settings/cache_settings.h"
|
||||
#include "../game/selection_subtype_tally.h"
|
||||
#include "game_scene.h"
|
||||
|
||||
#include <QAction>
|
||||
|
|
@ -79,12 +78,12 @@ GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, par
|
|||
totalCountLabel->setStyleSheet(totalCountLabelStyle);
|
||||
totalCountLabel->hide();
|
||||
|
||||
subtypeTallyContainer = new QWidget(this);
|
||||
subtypeTallyContainer->setStyleSheet(subtypeTallyLabelStyle);
|
||||
subtypeTallyLayout = new QGridLayout(subtypeTallyContainer);
|
||||
subtypeTallyLayout->setContentsMargins(2, 2, 2, 2);
|
||||
subtypeTallyLayout->setSpacing(2);
|
||||
subtypeTallyContainer->hide();
|
||||
tallyContainer = new QWidget(this);
|
||||
tallyContainer->setStyleSheet(subtypeTallyLabelStyle);
|
||||
tallyLayout = new QGridLayout(tallyContainer);
|
||||
tallyLayout->setContentsMargins(2, 2, 2, 2);
|
||||
tallyLayout->setSpacing(2);
|
||||
tallyContainer->hide();
|
||||
}
|
||||
|
||||
void GameView::resizeEvent(QResizeEvent *event)
|
||||
|
|
@ -177,14 +176,14 @@ void GameView::refreshShortcuts()
|
|||
SettingsCache::instance().shortcuts().getShortcut("Player/aCloseMostRecentZoneView"));
|
||||
}
|
||||
|
||||
void GameView::clearSubtypeLabels()
|
||||
void GameView::clearTallyLabels()
|
||||
{
|
||||
QtUtils::clearLayoutRec(subtypeTallyLayout);
|
||||
QtUtils::clearLayoutRec(tallyLayout);
|
||||
}
|
||||
|
||||
QSize GameView::rebuildSubtypeLabels(const QList<SubtypeEntry> &entries)
|
||||
QSize GameView::rebuildTallyLabels(const QList<TallyRow> &entries)
|
||||
{
|
||||
clearSubtypeLabels();
|
||||
clearTallyLabels();
|
||||
|
||||
const QString nameStyle = QStringLiteral("color: white; font-size: 12px; background: transparent;");
|
||||
const QString countStyle =
|
||||
|
|
@ -195,16 +194,16 @@ QSize GameView::rebuildSubtypeLabels(const QList<SubtypeEntry> &entries)
|
|||
int maxCountWidth = 0;
|
||||
|
||||
int row = 0;
|
||||
for (const SubtypeEntry &entry : entries) {
|
||||
auto *nameLabel = new QLabel(entry.name, subtypeTallyContainer);
|
||||
for (const TallyRow &entry : entries) {
|
||||
auto *nameLabel = new QLabel(entry.name, tallyContainer);
|
||||
nameLabel->setStyleSheet(nameStyle);
|
||||
nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
subtypeTallyLayout->addWidget(nameLabel, row, 0);
|
||||
tallyLayout->addWidget(nameLabel, row, 0);
|
||||
|
||||
auto *countLabel = new QLabel(QString::number(entry.count), subtypeTallyContainer);
|
||||
auto *countLabel = new QLabel(entry.value, tallyContainer);
|
||||
countLabel->setStyleSheet(countStyle);
|
||||
countLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
subtypeTallyLayout->addWidget(countLabel, row, 1);
|
||||
tallyLayout->addWidget(countLabel, row, 1);
|
||||
|
||||
QSize nameSize = nameLabel->sizeHint();
|
||||
QSize countSize = countLabel->sizeHint();
|
||||
|
|
@ -215,9 +214,9 @@ QSize GameView::rebuildSubtypeLabels(const QList<SubtypeEntry> &entries)
|
|||
++row;
|
||||
}
|
||||
|
||||
int spacing = subtypeTallyLayout->spacing();
|
||||
int margins = subtypeTallyLayout->contentsMargins().left() + subtypeTallyLayout->contentsMargins().right();
|
||||
int verticalMargins = subtypeTallyLayout->contentsMargins().top() + subtypeTallyLayout->contentsMargins().bottom();
|
||||
int spacing = tallyLayout->spacing();
|
||||
int margins = tallyLayout->contentsMargins().left() + tallyLayout->contentsMargins().right();
|
||||
int verticalMargins = tallyLayout->contentsMargins().top() + tallyLayout->contentsMargins().bottom();
|
||||
|
||||
int width = maxNameWidth + spacing + maxCountWidth + margins;
|
||||
int height = totalHeight + (row - 1) * spacing + verticalMargins;
|
||||
|
|
@ -248,28 +247,31 @@ void GameView::updateTotalSelectionCount(const QSize &viewSize)
|
|||
}
|
||||
|
||||
if (!SettingsCache::instance().getShowSubtypeSelectionTally() || count <= 1) {
|
||||
subtypeTallyContainer->hide();
|
||||
cachedSubtypeEntries.clear();
|
||||
tallyContainer->hide();
|
||||
cachedTallyRows.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
TallyType tallyType =
|
||||
SettingsCache::instance().getShowSubtypeSelectionTally() ? TallyType::Subtypes : TallyType::None;
|
||||
|
||||
GameScene *gameScene = static_cast<GameScene *>(scene());
|
||||
QList<SubtypeEntry> entries = SelectionSubtypeTally::countSubtypes(gameScene->selectedCards());
|
||||
QList<TallyRow> entries = Tally::compute(gameScene->selectedCards(), tallyType);
|
||||
|
||||
if (entries.isEmpty()) {
|
||||
subtypeTallyContainer->hide();
|
||||
cachedSubtypeEntries.clear();
|
||||
tallyContainer->hide();
|
||||
cachedTallyRows.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Only rebuild labels if entries changed
|
||||
QSize containerSize;
|
||||
if (entries != cachedSubtypeEntries) {
|
||||
cachedSubtypeEntries = entries;
|
||||
containerSize = rebuildSubtypeLabels(entries);
|
||||
subtypeTallyContainer->resize(containerSize);
|
||||
if (entries != cachedTallyRows) {
|
||||
cachedTallyRows = entries;
|
||||
containerSize = rebuildTallyLabels(entries);
|
||||
tallyContainer->resize(containerSize);
|
||||
} else {
|
||||
containerSize = subtypeTallyContainer->size();
|
||||
containerSize = tallyContainer->size();
|
||||
}
|
||||
|
||||
int x = availableWidth - containerSize.width() - kMarginInPixels;
|
||||
|
|
@ -283,8 +285,8 @@ void GameView::updateTotalSelectionCount(const QSize &viewSize)
|
|||
|
||||
y = qMax(kMarginInPixels, y);
|
||||
|
||||
subtypeTallyContainer->move(x, y);
|
||||
subtypeTallyContainer->show();
|
||||
tallyContainer->move(x, y);
|
||||
tallyContainer->show();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef GAMEVIEW_H
|
||||
#define GAMEVIEW_H
|
||||
|
||||
#include "../game/selection_subtype_tally.h"
|
||||
#include "tally/tally.h"
|
||||
|
||||
#include <QGraphicsView>
|
||||
|
||||
|
|
@ -24,13 +24,13 @@ private:
|
|||
QRubberBand *rubberBand;
|
||||
QLabel *dragCountLabel;
|
||||
QLabel *totalCountLabel;
|
||||
QWidget *subtypeTallyContainer;
|
||||
QGridLayout *subtypeTallyLayout;
|
||||
QWidget *tallyContainer;
|
||||
QGridLayout *tallyLayout;
|
||||
QPointF selectionOrigin;
|
||||
QList<SubtypeEntry> cachedSubtypeEntries; ///< Cached entries to avoid redundant rebuilds
|
||||
QList<TallyRow> cachedTallyRows; ///< Cached entries to avoid redundant rebuilds
|
||||
|
||||
QSize rebuildSubtypeLabels(const QList<SubtypeEntry> &entries);
|
||||
void clearSubtypeLabels();
|
||||
QSize rebuildTallyLabels(const QList<TallyRow> &entries);
|
||||
void clearTallyLabels();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "selection_subtype_tally.h"
|
||||
#include "subtype_tally.h"
|
||||
|
||||
#include "../game_graphics/board/card_item.h"
|
||||
#include "../board/card_item.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <algorithm>
|
||||
|
|
@ -19,12 +19,19 @@ QStringList extractSubtypesFromFace(const QString &faceType)
|
|||
return {};
|
||||
}
|
||||
|
||||
/** @brief A single subtype (e.g., "Goblin", "Warrior") with its occurrence count. */
|
||||
struct SubtypeEntry
|
||||
{
|
||||
QString name;
|
||||
int count;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace SelectionSubtypeTally
|
||||
namespace SubtypeTally
|
||||
{
|
||||
|
||||
QList<SubtypeEntry> countSubtypes(const QList<CardItem *> &cards)
|
||||
QList<TallyRow> countSubtypes(const QList<CardItem *> &cards)
|
||||
{
|
||||
QMap<QString, int> subtypeCounts;
|
||||
|
||||
|
|
@ -58,7 +65,12 @@ QList<SubtypeEntry> countSubtypes(const QList<CardItem *> &cards)
|
|||
return a.name < b.name;
|
||||
});
|
||||
|
||||
return entries;
|
||||
// convert entries into TallyRows
|
||||
QList<TallyRow> rows = QList<TallyRow>(entries.size());
|
||||
std::transform(entries.begin(), entries.end(), rows.begin(),
|
||||
[](const SubtypeEntry &e) { return TallyRow{e.name, QString::number(e.count)}; });
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
} // namespace SelectionSubtypeTally
|
||||
} // namespace SubtypeTally
|
||||
26
cockatrice/src/game_graphics/tally/subtype_tally.h
Normal file
26
cockatrice/src/game_graphics/tally/subtype_tally.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef SELECTION_SUBTYPE_TALLY_H
|
||||
#define SELECTION_SUBTYPE_TALLY_H
|
||||
|
||||
#include "tally.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
class CardItem;
|
||||
|
||||
/**
|
||||
* @brief Extracts and tallies subtypes from selected cards.
|
||||
*/
|
||||
namespace SubtypeTally
|
||||
{
|
||||
/**
|
||||
* @brief Parses card type lines and counts each subtype occurrence.
|
||||
*
|
||||
* Skips face-down cards and cards without type info.
|
||||
* @param cards The list of selected card items to analyze.
|
||||
* @return Entries sorted by count ascending, then alphabetically.
|
||||
*/
|
||||
QList<TallyRow> countSubtypes(const QList<CardItem *> &cards);
|
||||
} // namespace SubtypeTally
|
||||
|
||||
#endif
|
||||
15
cockatrice/src/game_graphics/tally/tally.cpp
Normal file
15
cockatrice/src/game_graphics/tally/tally.cpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#include "tally.h"
|
||||
|
||||
#include "subtype_tally.h"
|
||||
|
||||
QList<TallyRow> Tally::compute(const QList<CardItem *> &cards, const TallyType type)
|
||||
{
|
||||
switch (type) {
|
||||
case TallyType::None:
|
||||
return {};
|
||||
case TallyType::Subtypes:
|
||||
return SubtypeTally::countSubtypes(cards);
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
40
cockatrice/src/game_graphics/tally/tally.h
Normal file
40
cockatrice/src/game_graphics/tally/tally.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef COCKATRICE_TALLY_H
|
||||
#define COCKATRICE_TALLY_H
|
||||
#include <QString>
|
||||
|
||||
class CardItem;
|
||||
|
||||
/** @brief A single row of the tally output. */
|
||||
struct TallyRow
|
||||
{
|
||||
QString name; ///< The row name (displayed on the left)
|
||||
QString value; ///< Value for the row (displayed on the right)
|
||||
|
||||
bool operator==(const TallyRow &) const = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* The tally type
|
||||
*/
|
||||
enum class TallyType
|
||||
{
|
||||
None,
|
||||
Subtypes,
|
||||
};
|
||||
|
||||
namespace Tally
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Analyzes the selected cards according to the tally type and builds the resulting tally rows.
|
||||
* This forwards the cards to the code for that tally type.
|
||||
*
|
||||
* @param cards The list of selected card items to analyze.
|
||||
* @param type The type of tally to do
|
||||
* @return Rows sorted in top-to-bottom display order
|
||||
*/
|
||||
QList<TallyRow> compute(const QList<CardItem *> &cards, TallyType type);
|
||||
|
||||
} // namespace Tally
|
||||
|
||||
#endif // COCKATRICE_TALLY_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue