#include "BalancingWindow.h" #include #include BalancingWindow::BalancingWindow(const BalancingConfig& balancingConfig, const GameConfig& gameConfig, QWidget* parent) : QWidget(parent) , m_gameConfig(gameConfig) , m_nextSeed(0) { setWindowTitle("DotaFactory — Balancing Tool"); resize(800, 600); QVBoxLayout* mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); m_startAllButton = new QPushButton("Start All", this); mainLayout->addWidget(m_startAllButton); connect(m_startAllButton, &QPushButton::clicked, this, &BalancingWindow::startAll); QScrollArea* scrollArea = new QScrollArea(this); scrollArea->setWidgetResizable(true); QWidget* scrollContent = new QWidget(scrollArea); QVBoxLayout* contentLayout = new QVBoxLayout(scrollContent); contentLayout->setSpacing(8); contentLayout->setContentsMargins(8, 8, 8, 8); for (const ArenaConfig& arenaConfig : balancingConfig.arenas) { int index = static_cast(m_arenas.size()); ArenaEntry entry; entry.config = arenaConfig; entry.simulation = std::make_unique( m_gameConfig, arenaConfig, m_nextSeed++); entry.widget = new ArenaWidget(arenaConfig.name, scrollContent); contentLayout->addWidget(entry.widget); entry.widget->updateStatus(entry.simulation->status()); connect(entry.widget, &ArenaWidget::startRequested, this, [this, index]() { startArena(index); }); m_arenas.push_back(std::move(entry)); } contentLayout->addStretch(); scrollArea->setWidget(scrollContent); mainLayout->addWidget(scrollArea); m_pollTimer = new QTimer(this); connect(m_pollTimer, &QTimer::timeout, this, &BalancingWindow::pollStatuses); m_pollTimer->start(100); } BalancingWindow::~BalancingWindow() { m_pollTimer->stop(); for (ArenaEntry& entry : m_arenas) { entry.simulation->requestStop(); } for (ArenaEntry& entry : m_arenas) { if (entry.worker.joinable()) { entry.worker.join(); } } } void BalancingWindow::pollStatuses() { for (ArenaEntry& entry : m_arenas) { if (entry.worker.joinable()) { const ArenaStatus status = entry.simulation->status(); entry.widget->updateStatus(status); } } updateStartAllButton(); } void BalancingWindow::startAll() { for (int i = 0; i < static_cast(m_arenas.size()); ++i) { startArena(i); } } void BalancingWindow::startArena(int index) { ArenaEntry& entry = m_arenas[index]; if (entry.worker.joinable()) { entry.simulation->requestStop(); entry.worker.join(); } entry.simulation = std::make_unique( m_gameConfig, entry.config, m_nextSeed++); entry.widget->startSimulation(); entry.widget->updateStatus(entry.simulation->status()); ArenaSimulation* sim = entry.simulation.get(); entry.worker = std::thread([sim]() { sim->run(); }); updateStartAllButton(); } void BalancingWindow::updateStartAllButton() { for (ArenaEntry& entry : m_arenas) { if (!entry.worker.joinable() || entry.simulation->status().finished) { m_startAllButton->setEnabled(true); return; } } m_startAllButton->setEnabled(false); }