diff options
Diffstat (limited to 'quacker')
-rw-r--r-- | quacker/macondo.cpp | 37 | ||||
-rw-r--r-- | quacker/macondo.h | 26 | ||||
-rw-r--r-- | quacker/macondobackend.cpp | 21 | ||||
-rw-r--r-- | quacker/macondobackend.h | 6 | ||||
-rw-r--r-- | quacker/quacker.cpp | 28 | ||||
-rw-r--r-- | quacker/quacker.h | 12 |
6 files changed, 81 insertions, 49 deletions
diff --git a/quacker/macondo.cpp b/quacker/macondo.cpp index c089b42..55d5deb 100644 --- a/quacker/macondo.cpp +++ b/quacker/macondo.cpp @@ -5,45 +5,48 @@ #include <QGridLayout> #include <QPushButton> +#include <QCheckBox> -Macondo::Macondo(Quackle::Game *game) : QWidget() { +Macondo::Macondo(Quackle::Game *game, MoveBox *moveBox) : View() { m_game = game; + m_moveBox = moveBox; QGridLayout *layout = new QGridLayout(this); - m_moveBox = new MoveBox; - m_simulateButton = new QPushButton(tr("Simulate")); + m_useMacondo = new QCheckBox(tr("Use Macondo for 'Simulate'")); layout->setAlignment(Qt::AlignTop); - layout->addWidget(m_simulateButton, 0, 0); - layout->addWidget(m_moveBox, 1, 0); + layout->addWidget(m_useMacondo, 0, 0); const char *home = getenv("HOME"); // TODO: configurable path std::string execPath = home ? home : "/"; execPath += "/apps/macondo/macondo"; initOptions = std::make_unique<MacondoInitOptions>(execPath); m_backend = new MacondoBackend(game, *initOptions); - connect(m_simulateButton, SIGNAL(clicked()), this, SLOT(simulate())); - connect(m_backend, SIGNAL(gotSimMoves(const Quackle::MoveList &)), this, SLOT(gotSimMoves(const Quackle::MoveList &))); + connect(m_backend, SIGNAL(gotSimMoves(const Quackle::MoveList *)), this, SIGNAL(newMoves(const Quackle::MoveList *))); } -Macondo::~Macondo() {} +Macondo::~Macondo() { + delete m_backend; +} void Macondo::simulate() { + if (m_backend->isRunning()) { + // stop analysis + stop(); + return; + } MacondoSimulateOptions options; m_backend->simulate(options); - m_moveBox->positionChanged(&m_game->currentPosition()); } - void Macondo::setGame(Quackle::Game *game) { delete m_backend; m_backend = new MacondoBackend(game, *initOptions); m_game = game; } -void Macondo::gotSimMoves(const Quackle::MoveList &moves) { - m_moveBox->movesChanged(&moves); - /*printf("got %zu moves\n",moves.size()); - for (const Quackle::Move &move: moves) { - std::cout << move << std::endl; - } - */ +void Macondo::stop() { + m_backend->stop(); +} + +bool Macondo::useForSimulation() const { + return m_useMacondo->isChecked(); } diff --git a/quacker/macondo.h b/quacker/macondo.h index 18441b5..de12fe1 100644 --- a/quacker/macondo.h +++ b/quacker/macondo.h @@ -1,9 +1,10 @@ #ifndef MACONDO_H #define MACONDO_H -#include <QWidget> +#include "view.h" +#include "game.h" -class QPushButton; +class QCheckBox; class QTimer; namespace Quackle { class Game; @@ -12,27 +13,26 @@ namespace Quackle { class MacondoBackend; struct MacondoInitOptions; class MoveBox; -class Macondo : public QWidget { +class Macondo : public View { Q_OBJECT public: - Macondo(Quackle::Game *); + Macondo(Quackle::Game *, MoveBox *); ~Macondo(); void setGame(Quackle::Game *); + // stop current analysis + void stop(); + // should Macondo be used for simulations? + bool useForSimulation() const; +signals: + void newMoves(const Quackle::MoveList *); public slots: void simulate(); -private slots: - void gotSimMoves(const Quackle::MoveList &moves); private: - enum class Command { - None, - Simulate, - Solve, - }; - QPushButton *m_simulateButton; + QCheckBox *m_useMacondo; Quackle::Game *m_game; MacondoBackend *m_backend; + Quackle::MoveList m_moves; int m_viewingPlyNumber = 0; - Command m_command = Command::None; MoveBox *m_moveBox; std::unique_ptr<MacondoInitOptions> initOptions; }; diff --git a/quacker/macondobackend.cpp b/quacker/macondobackend.cpp index d109d53..2712512 100644 --- a/quacker/macondobackend.cpp +++ b/quacker/macondobackend.cpp @@ -218,7 +218,7 @@ void MacondoBackend::timer() { if (!moves.empty()) { // at this point the GCG is definitely fully loaded removeTempGCG(); - emit gotSimMoves(moves); + emit gotSimMoves(&moves); } } break; @@ -270,11 +270,12 @@ void MacondoBackend::loadGCG() { } void MacondoBackend::killProcess() { - if (m_process) { - m_process->kill(); - m_process->deleteLater(); - m_process = nullptr; - } + // This will give an annoying "destroyed while process running" message, + // but there's no way of avoiding it while keeping this method synchronous. + // (Destroying the process while it's running does what we want anyways, + // i.e., kills it) + delete m_process; + m_process = nullptr; } void MacondoBackend::processFinished(int, QProcess::ExitStatus) { @@ -293,3 +294,11 @@ MacondoBackend::~MacondoBackend() { m_process->kill(); } } + + +void MacondoBackend::stop() { + killProcess(); + removeTempGCG(); + m_runningSimulation = false; + m_command = Command::None; +} diff --git a/quacker/macondobackend.h b/quacker/macondobackend.h index f61ae11..9d327d2 100644 --- a/quacker/macondobackend.h +++ b/quacker/macondobackend.h @@ -28,8 +28,11 @@ public: void simulate(const MacondoSimulateOptions &); ~MacondoBackend(); std::string getSimResults(); + inline bool isRunning() const { return m_command != Command::None; } + // stop current Macondo analysis + void stop(); signals: - void gotSimMoves(const Quackle::MoveList &moves); + void gotSimMoves(const Quackle::MoveList *moves); private slots: void processStarted(); void processFinished(int, QProcess::ExitStatus); @@ -47,6 +50,7 @@ private: std::string m_tempGCG; QProcess *m_process = nullptr; QTimer *m_updateTimer = nullptr; + // is simulation being run right now? (i.e. has process been started & game been loaded?) bool m_runningSimulation = false; Quackle::Game *m_game; QByteArray m_processOutput; diff --git a/quacker/quacker.cpp b/quacker/quacker.cpp index c386968..6bb25fc 100644 --- a/quacker/quacker.cpp +++ b/quacker/quacker.cpp @@ -619,18 +619,21 @@ void TopLevel::updatePositionViews() updateListerDialogWithRack(); } -void TopLevel::updateMoveViews() +void TopLevel::updateMoveViews(const Quackle::MoveList *providedList) { - if (m_simulator->hasSimulationResults()) + Quackle::MoveList list; + if (providedList) { + list = *providedList; + } + else if (m_simulator->hasSimulationResults()) { - const Quackle::MoveList& moveList = m_simulator->moves(/* prune */ true, /* sort by win */ true); - emit movesChanged(&moveList); + list = m_simulator->moves(/* prune */ true, /* sort by win */ true); } else { - const Quackle::MoveList moveList = m_game->currentPosition().moves(); - emit movesChanged(&moveList); + list = m_game->currentPosition().moves(); } + emit movesChanged(&list); m_simulateAction->setEnabled(!m_game->currentPosition().moves().empty()); m_simulateDetailsAction->setEnabled(!m_game->currentPosition().moves().empty()); @@ -1067,6 +1070,15 @@ void TopLevel::simulateToggled(bool startSimulation) if (!m_game->hasPositions()) return; + if (m_macondo->useForSimulation()) { + if (startSimulation) { + m_macondo->simulate(); + } else { + m_macondo->stop(); + } + return; + } + simulate(startSimulation); if (startSimulation) @@ -2003,7 +2015,9 @@ void TopLevel::createWidgets() m_history = new History; plugIntoHistoryMatrix(m_history); - m_macondo = new Macondo(m_game); + m_macondo = new Macondo(m_game, m_moveBox); + plugIntoMatrix(m_macondo); + connect(m_macondo, SIGNAL(newMoves(const Quackle::MoveList *)), this, SLOT(updateMoveViews(const Quackle::MoveList *))); m_tabWidget = new QTabWidget; m_tabWidget->addTab(m_history, tr("Histor&y")); diff --git a/quacker/quacker.h b/quacker/quacker.h index cb47023..b9a9602 100644 --- a/quacker/quacker.h +++ b/quacker/quacker.h @@ -66,6 +66,7 @@ class BaseView; class HistoryView; class Letterbox; class ListerDialog; +class MoveBox; class QuackerSettings; class Settings; class SimViewer; @@ -200,10 +201,6 @@ protected slots: // update *positional* views - emit positionChanged void updatePositionViews(); - // updates move views from either simulation results if available - // or kibitzed moves - void updateMoveViews(); - // update history views when a new position is added void updateHistoryViews(); @@ -232,6 +229,11 @@ protected slots: void startBirthday(); void birthdayBash(); void birthdayGram(int index, bool on); +public slots: + // updates move views from either provided list, + // or simulation results if available, + // or kibitzed moves + void updateMoveViews(const Quackle::MoveList *list = nullptr); signals: // emitted when views (eg board) should update based on the @@ -321,7 +323,7 @@ private: HistoryView *m_dashboard; QWidget *m_choicesWidget; - View *m_moveBox; + MoveBox *m_moveBox; View *m_noteEditor; QFrame *m_frameWidget; |