Computation logic moved to helper funtction in separate file

This commit is contained in:
DawnFire42 2026-05-24 01:08:38 -04:00
parent 20c8bc1c1e
commit c947808547
No known key found for this signature in database
GPG key ID: 24BB855EE2911B33
4 changed files with 163 additions and 124 deletions

View file

@ -82,6 +82,7 @@ set(cockatrice_SOURCES
src/game_graphics/game_scene.cpp
src/game/game_state.cpp
src/game_graphics/game_view.cpp
src/game/selection_subtype_counter.cpp
src/game_graphics/hand_counter.cpp
src/game_graphics/log/message_log_widget.cpp
src/game/phase.cpp

View file

@ -0,0 +1,129 @@
#include "selection_subtype_counter.h"
#include "board/card_item.h"
#include <QMap>
#include <algorithm>
namespace SelectionSubtypeCounter
{
QStringList extractSubtypesFromFace(const QString &faceType)
{
QStringList parts = faceType.split(QStringLiteral(""));
if (parts.size() > 1) {
return parts[1].split(QStringLiteral(" "), Qt::SkipEmptyParts);
}
return {};
}
QList<MainTypeGroup> countSubtypes(const QList<CardItem *> &cards)
{
QMap<QString, QMap<QString, int>> subtypesByMainType;
QMap<QString, int> cardCountPerMainType;
for (CardItem *card : cards) {
if (card->getFaceDown() || card->getCard().isEmpty()) {
continue;
}
QString mainType = card->getCardInfo().getMainCardType();
if (mainType.isEmpty()) {
mainType = QStringLiteral("Other");
}
QString cardType = card->getCardInfo().getCardType();
QStringList cardFaces = cardType.split(QStringLiteral(" // "));
bool contributedSubtypes = false;
for (const QString &face : cardFaces) {
QStringList subtypes = extractSubtypesFromFace(face);
for (const QString &subtype : subtypes) {
subtypesByMainType[mainType][subtype]++;
contributedSubtypes = true;
}
}
if (contributedSubtypes) {
cardCountPerMainType[mainType]++;
}
}
QList<MainTypeGroup> groups;
for (auto it = subtypesByMainType.constBegin(); it != subtypesByMainType.constEnd(); ++it) {
MainTypeGroup group;
group.mainType = it.key();
group.cardCount = cardCountPerMainType.value(it.key(), 0);
for (auto subIt = it.value().constBegin(); subIt != it.value().constEnd(); ++subIt) {
group.subtypes.append({subIt.key(), subIt.value()});
}
// Sort subtypes: by count ascending, then alphabetically
std::sort(group.subtypes.begin(), group.subtypes.end(), [](const SubtypeEntry &a, const SubtypeEntry &b) {
if (a.count != b.count) {
return a.count < b.count;
}
return a.name < b.name;
});
groups.append(group);
}
// Sort groups: by card count ascending, then alphabetically by main type
std::sort(groups.begin(), groups.end(), [](const MainTypeGroup &a, const MainTypeGroup &b) {
if (a.cardCount != b.cardCount) {
return a.cardCount < b.cardCount;
}
return a.mainType < b.mainType;
});
return groups;
}
QString formatAsHtml(const QList<MainTypeGroup> &groups)
{
// Flatten to final ordered list
QList<SubtypeEntry> sortedEntries;
for (const MainTypeGroup &group : groups) {
for (const auto &entry : group.subtypes) {
sortedEntries.append(entry);
}
}
// Calculate padding widths
int maxNameLen = 0;
int maxCountLen = 0;
for (const auto &entry : sortedEntries) {
maxNameLen = qMax(maxNameLen, entry.name.length());
maxCountLen = qMax(maxCountLen, QString::number(entry.count).length());
}
// Format output
QStringList lines;
for (const auto &entry : sortedEntries) {
QString name = entry.name.toHtmlEscaped();
QString count = QString::number(entry.count);
QString namePadding = QString(QStringLiteral("&nbsp;")).repeated(maxNameLen - entry.name.length());
QString countPadding = QString(QStringLiteral("&nbsp;")).repeated(maxCountLen - count.length());
lines << QStringLiteral(
"%1%2 <span style='font-size:14px;font-weight:bold;vertical-align:middle;'>%3%4</span>")
.arg(namePadding, name, countPadding, count);
}
return QStringLiteral("<span style='font-family: monospace;'>") + lines.join(QStringLiteral("<br>")) +
QStringLiteral("</span>");
}
QString buildSubtypeCountText(const QList<CardItem *> &cards)
{
QList<MainTypeGroup> groups = countSubtypes(cards);
if (groups.isEmpty()) {
return QString();
}
return formatAsHtml(groups);
}
} // namespace SelectionSubtypeCounter

View file

@ -0,0 +1,31 @@
#ifndef SELECTION_SUBTYPE_COUNTER_H
#define SELECTION_SUBTYPE_COUNTER_H
#include <QList>
#include <QString>
#include <QStringList>
class CardItem;
struct SubtypeEntry
{
QString name;
int count;
};
struct MainTypeGroup
{
QString mainType;
int cardCount;
QList<SubtypeEntry> subtypes;
};
namespace SelectionSubtypeCounter
{
QStringList extractSubtypesFromFace(const QString &faceType);
QList<MainTypeGroup> countSubtypes(const QList<CardItem *> &cards);
QString formatAsHtml(const QList<MainTypeGroup> &groups);
QString buildSubtypeCountText(const QList<CardItem *> &cards);
} // namespace SelectionSubtypeCounter
#endif

View file

@ -1,15 +1,13 @@
#include "game_view.h"
#include "../client/settings/cache_settings.h"
#include "board/card_item.h"
#include "game_scene.h"
#include "selection_subtype_counter.h"
#include <QAction>
#include <QLabel>
#include <QMap>
#include <QResizeEvent>
#include <QRubberBand>
#include <algorithm>
// QRubberBand calls raise() in showEvent() and changeEvent() to stay on top of siblings.
// This subclass disables that behavior so dragCountLabel can appear above it.
@ -174,133 +172,13 @@ void GameView::refreshShortcuts()
SettingsCache::instance().shortcuts().getShortcut("Player/aCloseMostRecentZoneView"));
}
/** @brief Extracts subtypes from a card face type string (e.g., "Creature — Human Wizard" -> ["Human", "Wizard"]) */
static QStringList extractSubtypesFromFace(const QString &faceType)
{
QStringList parts = faceType.split(QStringLiteral(""));
if (parts.size() > 1) {
return parts[1].split(QStringLiteral(" "), Qt::SkipEmptyParts);
}
return {};
}
QString GameView::buildSubtypeCountText() const
{
GameScene *gameScene = dynamic_cast<GameScene *>(scene());
if (!gameScene) {
return QString();
}
// Map: main card type -> (subtype -> count)
QMap<QString, QMap<QString, int>> subtypesByMainType;
// Track cards contributing subtypes per main type (for group ordering)
QMap<QString, int> cardCountPerMainType;
for (CardItem *card : gameScene->selectedCards()) {
if (card->getFaceDown() || card->getCard().isEmpty()) {
continue;
}
QString mainType = card->getCardInfo().getMainCardType();
if (mainType.isEmpty()) {
mainType = QStringLiteral("Other");
}
QString cardType = card->getCardInfo().getCardType();
QStringList cardFaces = cardType.split(QStringLiteral(" // "));
bool contributedSubtypes = false;
for (const QString &face : cardFaces) {
QStringList subtypes = extractSubtypesFromFace(face);
for (const QString &subtype : subtypes) {
subtypesByMainType[mainType][subtype]++;
contributedSubtypes = true;
}
}
if (contributedSubtypes) {
cardCountPerMainType[mainType]++;
}
}
if (subtypesByMainType.isEmpty()) {
return QString();
}
// Build groups with sorted subtypes
struct MainTypeGroup
{
QString mainType;
int cardCount;
QList<QPair<QString, int>> subtypes;
};
QList<MainTypeGroup> groups;
for (auto it = subtypesByMainType.constBegin(); it != subtypesByMainType.constEnd(); ++it) {
MainTypeGroup group;
group.mainType = it.key();
group.cardCount = cardCountPerMainType.value(it.key(), 0);
for (auto subIt = it.value().constBegin(); subIt != it.value().constEnd(); ++subIt) {
group.subtypes.append({subIt.key(), subIt.value()});
}
/**
* Sort subtypes: by count ascending (lower counts at top of the list), then alphabetically.
* Since the subtype list displays above the total count label (bottom-right corner),
* ascending order places the most common subtypes visually adjacent to the total.
*/
std::sort(group.subtypes.begin(), group.subtypes.end(),
[](const QPair<QString, int> &a, const QPair<QString, int> &b) {
if (a.second != b.second) {
return a.second < b.second;
}
return a.first < b.first;
});
groups.append(group);
}
// Sort groups: by card count ascending, then alphabetically by main type
std::sort(groups.begin(), groups.end(), [](const MainTypeGroup &a, const MainTypeGroup &b) {
if (a.cardCount != b.cardCount) {
return a.cardCount < b.cardCount;
}
return a.mainType < b.mainType;
});
// Flatten to final ordered list
QList<QPair<QString, int>> sortedEntries;
for (const MainTypeGroup &group : groups) {
for (const auto &entry : group.subtypes) {
sortedEntries.append(entry);
}
}
// Calculate padding widths
int maxNameLen = 0;
int maxCountLen = 0;
for (const auto &entry : sortedEntries) {
maxNameLen = qMax(maxNameLen, entry.first.length());
maxCountLen = qMax(maxCountLen, QString::number(entry.second).length());
}
// Format output
QStringList lines;
for (const auto &entry : sortedEntries) {
QString name = entry.first.toHtmlEscaped();
QString count = QString::number(entry.second);
QString namePadding = QString(QStringLiteral("&nbsp;")).repeated(maxNameLen - entry.first.length());
QString countPadding = QString(QStringLiteral("&nbsp;")).repeated(maxCountLen - count.length());
lines << QStringLiteral(
"%1%2 <span style='font-size:14px;font-weight:bold;vertical-align:middle;'>%3%4</span>")
.arg(namePadding, name, countPadding, count);
}
return QStringLiteral("<span style='font-family: monospace;'>") + lines.join(QStringLiteral("<br>")) +
QStringLiteral("</span>");
return SelectionSubtypeCounter::buildSubtypeCountText(gameScene->selectedCards());
}
void GameView::updateSelectionCount(const QSize &viewSize)