summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-08-24 10:56:27 -0400
committerpommicket <pommicket@gmail.com>2025-08-24 10:56:27 -0400
commit82f08e0d21520a6c673a2a4ee5737f12752db6c5 (patch)
tree9db5ce3b5256e0bd8dc6c3d36c0caa88026241f3
parent8f5e37f02d9c9247461137edbdbce86e2d96ebb1 (diff)
Show Macondo log
-rw-r--r--quacker/macondo.cpp50
-rw-r--r--quacker/macondo.h12
-rw-r--r--quacker/macondobackend.cpp14
-rw-r--r--quacker/macondobackend.h1
4 files changed, 68 insertions, 9 deletions
diff --git a/quacker/macondo.cpp b/quacker/macondo.cpp
index 0cd0021..8272dd4 100644
--- a/quacker/macondo.cpp
+++ b/quacker/macondo.cpp
@@ -10,6 +10,7 @@
#include <QLineEdit>
#include <QMessageBox>
#include <QOperatingSystemVersion>
+#include <QPlainTextEdit>
#include <QPushButton>
#include <QSettings>
#include <QSpinBox>
@@ -45,6 +46,8 @@ Macondo::Macondo(Quackle::Game *game) : View() {
connect(m_execPath, SIGNAL(editingFinished()), this, SLOT(execPathChanged()));
m_solve = new QPushButton(tr("Solve"));
m_solve->setDisabled(true);
+ m_log = new QPlainTextEdit;
+ //m_log->setReadOnly(true);
QHBoxLayout *execPathLayout = new QHBoxLayout;
execPathLayout->addWidget(execPathLabel);
@@ -105,6 +108,7 @@ Macondo::Macondo(Quackle::Game *game) : View() {
layout->addWidget(pegBox);
layout->addWidget(endgameBox);
layout->addWidget(m_solve);
+ layout->addWidget(m_log, 1);
connect(m_solve, SIGNAL(clicked()), this, SLOT(solve()));
}
@@ -173,6 +177,7 @@ bool Macondo::simulate() {
}
if (isRunning())
stop();
+ clearLog();
MacondoSimulateOptions options;
return m_backend->simulate(options, m_movesFromKibitzer);
}
@@ -189,6 +194,7 @@ void Macondo::solve() {
if (wasSolving) {
emit stoppedSolver();
} else {
+ clearLog();
if (m_tilesUnseen > 7) {
MacondoPreEndgameOptions options;
options.endgamePlies = m_preEndgameMaxPlies->value();
@@ -230,6 +236,7 @@ void Macondo::gameChanged(Quackle::Game *game) {
void Macondo::connectBackendSignals() {
connect(m_backend, SIGNAL(gotMoves(const Quackle::MoveList &)), this, SLOT(gotMoves(const Quackle::MoveList &)));
connect(m_backend, SIGNAL(statusMessage(const QString &)), this, SIGNAL(statusMessage(const QString &)));
+ connect(m_backend, SIGNAL(newLogOutput(const QByteArray &)), this, SLOT(newLogOutput(const QByteArray &)));
}
void Macondo::stop() {
@@ -276,3 +283,46 @@ void Macondo::updateSolveButton() {
m_solve->setDisabled(true);
}
}
+
+void Macondo::clearLog() {
+ m_log->clear();
+ m_logANSIState = 0;
+}
+
+void Macondo::newLogOutput(const QByteArray &text) {
+ // annoying stuff to handle incomplete UTF-8 at end of text
+ QByteArray logContents = m_logPartialUtf8;
+ logContents.append(text);
+ size_t completeUtf8Len = 0;
+ while (completeUtf8Len < logContents.length()) {
+ uint8_t firstByte = logContents.at(completeUtf8Len);
+ size_t codepointLen = (firstByte & 0xe0) == 0xc0 ? 2
+ : (firstByte & 0xf0) == 0xe0 ? 3
+ : (firstByte & 0xf8) == 0xf0 ? 4 : 1;
+ if (completeUtf8Len + codepointLen > logContents.length()) break;
+ completeUtf8Len += codepointLen;
+ }
+ m_logPartialUtf8 = QByteArray(text.constData() + completeUtf8Len, text.length() - completeUtf8Len);
+ // remove ANSI escape sequences (color/formatting codes)
+ std::string filteredText;
+ for (size_t i = 0; i < completeUtf8Len; i++) {
+ uint8_t byte = text.at(i);
+ if (m_logANSIState == 0 && byte == 0x1b) {
+ m_logANSIState = 1;
+ } else if (m_logANSIState == 1 && byte == '[') {
+ m_logANSIState = 2;
+ } else if (m_logANSIState == 2 && byte >= 0x20 && byte < 0x40) {
+ // continuation of ANSI escape sequence
+ } else if (m_logANSIState == 2 && byte >= 0x40 && byte < 0x80) {
+ // terminator for ANSI escape sequence
+ m_logANSIState = 0;
+ } else {
+ m_logANSIState = 0;
+ filteredText.push_back(byte);
+ }
+ }
+ m_log->moveCursor(QTextCursor::MoveOperation::End);
+ m_log->insertPlainText(QString::fromStdString(filteredText));
+ m_log->moveCursor(QTextCursor::MoveOperation::End);
+ m_log->centerCursor();
+}
diff --git a/quacker/macondo.h b/quacker/macondo.h
index d56a577..a8a61b9 100644
--- a/quacker/macondo.h
+++ b/quacker/macondo.h
@@ -4,13 +4,14 @@
#include "view.h"
#include "game.h"
+class MacondoBackend;
+struct MacondoInitOptions;
+class MoveBox;
class QCheckBox;
class QPushButton;
class QLineEdit;
+class QPlainTextEdit;
class QSpinBox;
-class MacondoBackend;
-struct MacondoInitOptions;
-class MoveBox;
class Macondo : public View {
Q_OBJECT
@@ -39,10 +40,12 @@ public slots:
void gameChanged(Quackle::Game *game) override;
void positionChanged(const Quackle::GamePosition *position) override;
private slots:
+ void newLogOutput(const QByteArray &text);
void gotMoves(const Quackle::MoveList &moves);
void execPathChanged();
void chooseExecPath();
private:
+ void clearLog();
void setExecPath(const std::string &);
void connectBackendSignals();
bool checkExecPath();
@@ -66,11 +69,14 @@ private:
QSpinBox *m_preEndgameMaxPlies;
QPushButton *m_solve;
+ QPlainTextEdit *m_log;
+ QByteArray m_logPartialUtf8;
Quackle::Game *m_game;
MacondoBackend *m_backend;
Quackle::MoveList m_movesFromKibitzer;
int m_tilesUnseen = 93;
int m_viewingPlyNumber = 0;
+ int m_logANSIState = 0;
bool m_anyUpdates = false;
bool m_isSolving = false;
std::unique_ptr<MacondoInitOptions> m_initOptions;
diff --git a/quacker/macondobackend.cpp b/quacker/macondobackend.cpp
index 6ec1e85..628066a 100644
--- a/quacker/macondobackend.cpp
+++ b/quacker/macondobackend.cpp
@@ -413,15 +413,17 @@ void MacondoBackend::timer() {
bool anyNewOutput = false;
if (m_process) {
QByteArray data = m_process->readAllStandardError();
- anyNewOutput |= data.size() != 0;
- fprintf(stderr,"%.*s",data.size(), data.constData());
+ if (data.size()) {
+ anyNewOutput = true;
+ emit newLogOutput(data);
+ }
+ //fprintf(stderr,"%.*s",data.size(), data.constData());
m_processStderr.append(data);
data = m_process->readAllStandardOutput();
- anyNewOutput |= data.size() != 0;
m_processOutput.append(data);
- if (true) {
- // print Macondo stdout
- printf("%.*s",data.size(), data.constData());
+ if (data.size()) {
+ anyNewOutput = true;
+ emit newLogOutput(data);
}
fflush(stdout);
}
diff --git a/quacker/macondobackend.h b/quacker/macondobackend.h
index 981ab1e..28ba65c 100644
--- a/quacker/macondobackend.h
+++ b/quacker/macondobackend.h
@@ -50,6 +50,7 @@ public:
signals:
void gotMoves(const Quackle::MoveList &moves);
void statusMessage(const QString &message);
+ void newLogOutput(const QByteArray &log);
private slots:
void processStarted();
void processFinished(int, QProcess::ExitStatus);