From 9589072687726dd51776b0e952625ae1996f4721 Mon Sep 17 00:00:00 2001 From: Sebastiano Tronto Date: Wed, 16 Apr 2025 09:56:55 +0200 Subject: Added rudimentary QT UI --- qt/adapter.cpp | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 qt/adapter.cpp (limited to 'qt/adapter.cpp') diff --git a/qt/adapter.cpp b/qt/adapter.cpp new file mode 100644 index 0000000..3711fa4 --- /dev/null +++ b/qt/adapter.cpp @@ -0,0 +1,140 @@ +#include "adapter.h" + +#include +#include +#include +#include +#include +#include + +void logWrapper(const char *str, void *data) +{ + auto f = *reinterpret_cast*>(data); + f(str); +} + +NissyAdapter::NissyAdapter() +{ + std::vector solverNames { + "h48h3k2" + }; + + for (auto s : solverNames) + initSolver(s); + + writeLog = [&](const char *str) { + emit appendLog(QString::fromStdString(str)); + }; + + nissy::set_logger(&logWrapper, &writeLog); +} + +void NissyAdapter::initSolver(const std::string& s) { + auto se = nissy::solver::get(s); + if (std::holds_alternative(se)) { + qDebug("Error loading solver!"); + return; + } + auto ss = std::get(se); + solvers.push_back(ss); +} + +bool NissyAdapter::loadSolverData(nissy::solver& solver) { + if (solver.data_checked) + return true; + + std::filesystem::path filePath("./tables/" + solver.id); + if (!std::filesystem::exists(filePath)) { + auto err = solver.generate_data(); + if (!err.ok()) { + emit solverError(QString("Error generating data!")); + return false; + } + std::filesystem::create_directory("./tables/"); + std::ofstream ofs(filePath, std::ios::binary); + ofs.write(reinterpret_cast(solver.data.data()), + solver.size); + ofs.close(); + } else { + std::ifstream ifs(filePath, std::ios::binary); + solver.read_data(ifs); + ifs.close(); + } + + if (!solver.check_data().ok()) { + emit solverError(QString("Error reading data!")); + return false; + } + + return true; +} + +Q_INVOKABLE bool NissyAdapter::isValidScramble(QString qscr) +{ + nissy::cube c; + return c.move(qscr.toStdString()).ok(); +} + +Q_INVOKABLE void NissyAdapter::requestSolve( + QString scramble, + QString solver, + int minmoves, + int maxmoves, + int maxsolutions, + int optimal +) +{ + nissy::cube c; + if (!c.move(scramble.toStdString()).ok()) { + emit solverError(QString("Unexpected error: invalid scramble")); + return; + } + + nissy::solver *ss = nullptr; + for (auto& s : solvers) + if (s.name == solver) + ss = &s; + if (ss == nullptr) { + std::string msg = "Error: solver '" + solver.toStdString() + + "' not available"; + emit solverError(QString::fromStdString(msg)); + return; + } + + SolveOptions opts{c, ss, (unsigned)minmoves, (unsigned)maxmoves, + (unsigned)maxsolutions, optimal}; + auto _ = QtConcurrent::run(&NissyAdapter::startSolve, this, opts); + return; +} + +void NissyAdapter::startSolve(SolveOptions opts) +{ + loadSolverData(*opts.solver); + + auto result = opts.solver->solve(opts.cube, nissy::nissflag::NORMAL, + opts.minmoves, opts.maxmoves, opts.maxsolutions, opts.optimal, 8); + + if (!result.err.ok()) { + std::string msg = "Error computing solutions: " + + std::to_string(result.err.value); + emit solverError(QString::fromStdString(msg)); + return; + } + + auto& sols = result.solutions; + if (sols.size() == 0) { + emit solutionsReady("No solution found", ""); + } else { + std::stringstream hs; + hs << "Found " << sols.size() << " solution" + << (sols.size() > 1 ? "s:" : ":"); + + std::stringstream ss; + for (auto s : sols) { + auto n = nissy::count_moves(s).value; + ss << s << "(" << n << ")" << std::endl; // TODO: remove last newline + } + emit solutionsReady(QString::fromStdString(hs.str()), + QString::fromStdString(ss.str())); + } +} -- cgit v1.3