qt-experiments

Experiments with QT framework and nissy
git clone https://git.tronto.net/qt-experiments
Download | Log | Files | Refs | Submodules | README

adapter.cpp (3990B)


      1 #include "adapter.h"
      2 
      3 #include <fstream>
      4 #include <sstream>
      5 #include <string>
      6 #include <vector>
      7 #include <QDebug>
      8 #include <QtConcurrent/QtConcurrent>
      9 
     10 const std::string tablesdir = "../nissy-core/tables/";
     11 
     12 void logWrapper(const char *str, void *data)
     13 {
     14 	auto f = *reinterpret_cast<std::function<void(std::string)>*>(data);
     15 	f(std::string{str});
     16 }
     17 
     18 NissyAdapter::NissyAdapter()
     19 {
     20 	// TODO: this list must be kept in sync with UI code, it is a bit ugly
     21 	std::vector<std::string> solverNames {
     22 		"h48h0k4",
     23 		"h48h1k2",
     24 		"h48h2k2",
     25 		"h48h3k2",
     26 		"h48h7k2",
     27 	};
     28 
     29 	for (auto s : solverNames)
     30 		initSolver(s);
     31 
     32 	writeLog = [&](std::string str) {
     33 		emit appendLog(QString::fromStdString(str));
     34 	};
     35 
     36 	nissy::set_logger(&logWrapper, &writeLog);
     37 }
     38 
     39 void NissyAdapter::initSolver(const std::string& s) {
     40 	auto se = nissy::solver::get(s);
     41 	if (std::holds_alternative<nissy::error>(se)) {
     42 		qDebug("Error loading solver!");
     43 		return;
     44 	}
     45 	auto ss = std::get<nissy::solver>(se);
     46 	solvers.push_back(ss);
     47 }
     48 
     49 bool NissyAdapter::loadSolverData(nissy::solver& solver) {
     50 	if (solver.data_checked)
     51 		return true;
     52 
     53 	std::filesystem::path filePath(tablesdir + solver.id);
     54 	if (!std::filesystem::exists(filePath)) {
     55 		logLine("Data file for solver " + solver.name + " not found, "
     56 		    "generating it...");
     57 		auto err = solver.generate_data();
     58 		if (!err.ok()) {
     59 			emit solverError(QString("Error generating data!"));
     60 			return false;
     61 		}
     62 		std::filesystem::create_directory(tablesdir);
     63 		std::ofstream ofs(filePath, std::ios::binary);
     64 		ofs.write(reinterpret_cast<char *>(solver.data.data()),
     65 		    solver.size);
     66 		ofs.close();
     67 		logLine("Data generated succesfully");
     68 	} else {
     69 		logLine("Reading data for solver " + solver.name +
     70 		    " from file");
     71 		std::ifstream ifs(filePath, std::ios::binary);
     72 		solver.read_data(ifs);
     73 		ifs.close();
     74 		logLine("Data loaded");
     75 	}
     76 
     77 	logLine("Checking data integrity "
     78 	    "(this is done only once per solver per session)...");
     79 	if (!solver.check_data().ok()) {
     80 		emit solverError(QString("Error reading data!"));
     81 		return false;
     82 	}
     83 	logLine("Data checked");
     84 
     85 	return true;
     86 }
     87 
     88 Q_INVOKABLE bool NissyAdapter::isValidScramble(QString qscr)
     89 {
     90 	nissy::cube c;
     91 	return c.move(qscr.toStdString()).ok();
     92 }
     93 
     94 Q_INVOKABLE void NissyAdapter::requestSolve(
     95 	QString scramble,
     96 	QString solver,
     97 	int minmoves,
     98 	int maxmoves,
     99 	int maxsolutions,
    100 	int optimal
    101 )
    102 {
    103 	nissy::cube c;
    104 	if (!c.move(scramble.toStdString()).ok()) {
    105 		emit solverError(QString("Unexpected error: invalid scramble"));
    106 		return;
    107 	}
    108 
    109 	nissy::solver *ss = nullptr;
    110 	for (auto& s : solvers)
    111 		if (s.name == solver)
    112 			ss = &s;
    113 	if (ss == nullptr) {
    114 		std::string msg = "Error: solver '" + solver.toStdString()
    115 		    + "' not available";
    116 		emit solverError(QString::fromStdString(msg));
    117 		return;
    118 	}
    119 
    120 	SolveOptions opts{c, ss, (unsigned)minmoves, (unsigned)maxmoves,
    121 	    (unsigned)maxsolutions, (unsigned)optimal};
    122 	auto _ = QtConcurrent::run(&NissyAdapter::startSolve, this, opts);
    123 	return;
    124 }
    125 
    126 void NissyAdapter::startSolve(SolveOptions opts)
    127 {
    128 	loadSolverData(*opts.solver);
    129 
    130 	auto result = opts.solver->solve(opts.cube, nissy::nissflag::NORMAL,
    131 	    opts.minmoves, opts.maxmoves, opts.maxsolutions, opts.optimal, 8);
    132 
    133 	if (!result.err.ok()) {
    134 		std::string msg = "Error computing solutions: " +
    135 		    std::to_string(result.err.value);
    136 		emit solverError(QString::fromStdString(msg));
    137 		return;
    138 	}
    139 
    140 	auto& sols = result.solutions;
    141 	if (sols.size() == 0) {
    142 		emit solutionsReady("No solution found", "");
    143 	} else {
    144 		std::stringstream hs;
    145 		hs << "Found " << sols.size() << " solution"
    146 		    << (sols.size() > 1 ? "s:" : ":");
    147 
    148 		std::stringstream ss;
    149 		for (auto s : sols) {
    150 			auto n = nissy::count_moves(s).value;
    151 			ss << s << " (" << n << ")" << std::endl; // TODO: remove last newline
    152 		}
    153 		emit solutionsReady(QString::fromStdString(hs.str()),
    154 		   QString::fromStdString(ss.str()));
    155 	}
    156 }
    157 
    158 void NissyAdapter::logLine(std::string str)
    159 {
    160 	std::stringstream ss;
    161 	ss << str << std::endl;
    162 	writeLog(ss.str());
    163 }