allow to inspect balancing arena

This commit is contained in:
2026-05-03 21:17:43 +02:00
parent afd8cd28fa
commit 3ef32ee6ba
13 changed files with 851 additions and 4 deletions

View File

@@ -0,0 +1,187 @@
#include "InspectWindow.h"
#include <cmath>
#include <QCloseEvent>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QSignalMapper>
#include <QVBoxLayout>
#include "ArenaView.h"
const double InspectWindow::kSpeeds[] = { 0.0, 0.5, 1.0, 2.0, 4.0 };
const int InspectWindow::kSpeedCount = 5;
InspectWindow::InspectWindow(ArenaSimulation* sim, const VisualsConfig* visuals,
const std::string& arenaName, QWidget* parent)
: QWidget(parent)
, m_sim(sim)
{
setWindowTitle(QString("Inspect \u2014 %1").arg(QString::fromStdString(arenaName)));
resize(900, 700);
setAttribute(Qt::WA_DeleteOnClose, false);
QVBoxLayout* mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
// Header: arena name + speed buttons
{
QWidget* header = new QWidget(this);
QHBoxLayout* headerLayout = new QHBoxLayout(header);
headerLayout->setContentsMargins(8, 4, 8, 4);
headerLayout->setSpacing(8);
QLabel* nameLabel = new QLabel(QString::fromStdString(arenaName), header);
QFont nameFont = nameLabel->font();
nameFont.setBold(true);
nameFont.setPointSize(nameFont.pointSize() + 2);
nameLabel->setFont(nameFont);
headerLayout->addWidget(nameLabel);
headerLayout->addStretch();
const char* labels[] = { "0x", "0.5x", "1x", "2x", "4x" };
QSignalMapper* mapper = new QSignalMapper(this);
for (int i = 0; i < kSpeedCount; ++i)
{
QPushButton* btn = new QPushButton(labels[i], header);
btn->setCheckable(true);
btn->setChecked(i == 2);
headerLayout->addWidget(btn);
m_speedButtons.push_back(btn);
mapper->setMapping(btn, i);
connect(btn, &QPushButton::clicked,
mapper, qOverload<>(&QSignalMapper::map));
}
connect(mapper, qOverload<int>(&QSignalMapper::mapped),
this, &InspectWindow::onSpeedButton);
header->setFixedHeight(header->sizeHint().height());
mainLayout->addWidget(header);
}
// Arena view (center, stretch)
m_arenaView = new ArenaView(sim, visuals, this);
mainLayout->addWidget(m_arenaView, 1);
connect(m_arenaView, &ArenaView::speedChanged,
this, &InspectWindow::onSpeedChanged);
// Info panel (bottom)
{
QWidget* infoPanel = new QWidget(this);
QHBoxLayout* infoLayout = new QHBoxLayout(infoPanel);
infoLayout->setContentsMargins(8, 4, 8, 4);
infoLayout->setSpacing(16);
QVBoxLayout* team1Layout = new QVBoxLayout();
m_team1Header = new QLabel(infoPanel);
QFont headerFont = m_team1Header->font();
headerFont.setBold(true);
m_team1Header->setFont(headerFont);
team1Layout->addWidget(m_team1Header);
m_team1Content = new QLabel(infoPanel);
team1Layout->addWidget(m_team1Content);
team1Layout->addStretch();
infoLayout->addLayout(team1Layout);
QVBoxLayout* team2Layout = new QVBoxLayout();
m_team2Header = new QLabel(infoPanel);
m_team2Header->setFont(headerFont);
team2Layout->addWidget(m_team2Header);
m_team2Content = new QLabel(infoPanel);
team2Layout->addWidget(m_team2Content);
team2Layout->addStretch();
infoLayout->addLayout(team2Layout);
mainLayout->addWidget(infoPanel);
}
// Poll timer for info panel updates
m_pollTimer = new QTimer(this);
connect(m_pollTimer, &QTimer::timeout, this, &InspectWindow::pollStatus);
m_pollTimer->start(100);
// Show initial status
pollStatus();
setFocusPolicy(Qt::StrongFocus);
}
void InspectWindow::closeEvent(QCloseEvent* event)
{
m_pollTimer->stop();
emit closed();
event->accept();
}
void InspectWindow::keyPressEvent(QKeyEvent* event)
{
if (event->key() == Qt::Key_Space)
{
m_arenaView->togglePause();
}
else
{
QWidget::keyPressEvent(event);
}
}
void InspectWindow::onSpeedButton(int index)
{
if (index >= 0 && index < kSpeedCount)
{
m_arenaView->setGameSpeed(kSpeeds[index]);
}
}
void InspectWindow::onSpeedChanged(double multiplier)
{
for (int i = 0; i < kSpeedCount; ++i)
{
const bool active = (std::abs(kSpeeds[i] - multiplier) < 0.001);
m_speedButtons[static_cast<std::size_t>(i)]->setChecked(active);
}
}
void InspectWindow::pollStatus()
{
const ArenaStatus status = m_sim->status();
updateInfoPanel(status);
}
void InspectWindow::updateInfoPanel(const ArenaStatus& status)
{
for (int ti = 0; ti < 2; ++ti)
{
const ArenaStatus::TeamStatus& team = status.teams[ti];
QLabel* header = (ti == 0) ? m_team1Header : m_team2Header;
QLabel* content = (ti == 0) ? m_team1Content : m_team2Content;
if (status.finished && status.winnerTeam == ti)
{
header->setText("[WON] " + QString::fromStdString(team.name));
}
else
{
header->setText(QString::fromStdString(team.name));
}
QString lines;
for (const ArenaStatus::Entry& entry : team.entries)
{
if (!lines.isEmpty())
{
lines += "\n";
}
lines += QString("%1/%2 %3 L%4")
.arg(entry.surviving)
.arg(entry.total)
.arg(QString::fromStdString(entry.displayName))
.arg(entry.level);
}
content->setText(lines);
}
}