aboutsummaryrefslogtreecommitdiff
path: root/qt-quick/adapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt-quick/adapter.cpp')
-rw-r--r--qt-quick/adapter.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/qt-quick/adapter.cpp b/qt-quick/adapter.cpp
new file mode 100644
index 0000000..9594c56
--- /dev/null
+++ b/qt-quick/adapter.cpp
@@ -0,0 +1,163 @@
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
10const std::string tablesdir = "../nissy-core/tables/";
11
12void 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
18NissyAdapter::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
39void 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
49bool 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
88Q_INVOKABLE bool NissyAdapter::isValidScramble(QString qscr)
89{
90 nissy::cube c;
91 return c.move(qscr.toStdString()).ok();
92}
93
94Q_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
126void 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
158void NissyAdapter::logLine(std::string str)
159{
160 std::stringstream ss;
161 ss << str << std::endl;
162 writeLog(ss.str());
163}

Generated with cgit - Back to sebastiano.tronto.net