aboutsummaryrefslogtreecommitdiff
path: root/web/adapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'web/adapter.cpp')
-rw-r--r--web/adapter.cpp164
1 files changed, 164 insertions, 0 deletions
diff --git a/web/adapter.cpp b/web/adapter.cpp
new file mode 100644
index 0000000..1774187
--- /dev/null
+++ b/web/adapter.cpp
@@ -0,0 +1,164 @@
1#include "../cpp/nissy.h"
2
3#include <emscripten/bind.h>
4#include <map>
5#include <set>
6#include <string>
7#include <vector>
8
9extern "C" {
10 extern int addCallbackFunction(/* args intentionally unspecified */);
11 extern void callFunction(int, const char *);
12 extern int callFunctionInt(int);
13}
14
15static int logger_id = -1;
16
17void log(std::string s)
18{
19 if (logger_id == -1)
20 return;
21
22 callFunction(logger_id, s.c_str());
23}
24
25void log_wrapper(const char *cstr, void *data)
26{
27 log(cstr);
28}
29
30void set_logger(int id)
31{
32 logger_id = id;
33 nissy::set_logger(log_wrapper, NULL);
34}
35
36// Some of the solvers are not available to the JS interface because of
37// memory limitations.
38const std::set<std::string> available_solvers
39{
40 "h48h0k4",
41 "h48h1k2",
42 "h48h2k2",
43 "h48h3k2",
44 "h48h7k2",
45};
46
47std::map<std::string, nissy::solver> loaded_solvers;
48
49// TODO: this should ask the user if they want to download or generate.
50// TODO: this should also save the data to a file (IDBFS / NODEFS)
51bool init_solver(const std::string& name)
52{
53 auto se = nissy::solver::get(name);
54 nissy::solver solver = std::get<nissy::solver>(se);
55 log("Generating data for solver " + solver.name + "\n");
56 auto err = solver.generate_data();
57 if (!err.ok()) {
58 log("Error generating the data!\n");
59 return false;
60 }
61 log("Checking data integrity "
62 "(this is done only once per session per solver)...\n");
63 if (!solver.check_data().ok()) {
64 log("Error generating the data!\n");
65 return false;
66 }
67 loaded_solvers.insert({name, solver});
68 log("Data generated successfully, but not saved "
69 "(feature not yet available)\n");
70 return true;
71}
72
73bool solver_valid(const std::string& name)
74{
75 if (loaded_solvers.contains(name) ||
76 (available_solvers.contains(name) && init_solver(name)))
77 return true;
78
79 auto se = nissy::solver::get(name);
80 if (std::holds_alternative<nissy::solver>(se))
81 log("The solver " + name + " is not available in "
82 "the web version of Nissy. Use a native version.\n");
83 else
84 log("Invalid solver " + name + "\n");
85 return false;
86}
87
88int poll_status(void *arg)
89{
90 int id = *(int *)arg;
91 if (id == -1)
92 return nissy::status::RUN.value;
93 return callFunctionInt(id);
94}
95
96nissy::solver::solve_result solve(std::string name,
97 nissy::cube cube, nissy::nissflag nissflag, unsigned minmoves,
98 unsigned maxmoves, unsigned maxsols, unsigned optimal, unsigned threads,
99 int poll_status_id)
100{
101 if (!solver_valid(name))
102 return nissy::solver::solve_result
103 {.err = nissy::error::INVALID_SOLVER};
104
105 return loaded_solvers.at(name).solve(cube, nissflag, minmoves,
106 maxmoves, maxsols, optimal, threads, NULL, &poll_status_id);
107}
108
109EMSCRIPTEN_BINDINGS(Nissy)
110{
111 emscripten::class_<nissy::nissflag>("NissFlag")
112 .class_property("normal", &nissy::nissflag::NORMAL)
113 .class_property("inverse", &nissy::nissflag::INVERSE)
114 .class_property("mixed", &nissy::nissflag::MIXED)
115 .class_property("linear", &nissy::nissflag::LINEAR)
116 .class_property("all", &nissy::nissflag::ALL)
117 ;
118
119 emscripten::class_<nissy::error>("Error")
120 .function("ok", &nissy::error::ok)
121 .class_property("unsolvableWarning", &nissy::error::UNSOLVABLE_WARNING)
122 .class_property("unsolvableError", &nissy::error::UNSOLVABLE_ERROR)
123 .class_property("invalidCube", &nissy::error::INVALID_CUBE)
124 .class_property("invalidMoves", &nissy::error::INVALID_MOVES)
125 .class_property("invalidTrans", &nissy::error::INVALID_TRANS)
126 .class_property("invalidSolver", &nissy::error::INVALID_SOLVER)
127 .class_property("nullPointer", &nissy::error::NULL_POINTER)
128 .class_property("bufferSize", &nissy::error::BUFFER_SIZE)
129 .class_property("data", &nissy::error::DATA)
130 .class_property("options", &nissy::error::OPTIONS)
131 .class_property("unknown", &nissy::error::UNKNOWN)
132 ;
133
134 emscripten::constant("statusRUN", nissy::status::RUN.value);
135 emscripten::constant("statusSTOP", nissy::status::STOP.value);
136 emscripten::constant("statusPAUSE", nissy::status::PAUSE.value);
137 /*
138 emscripten::class_<nissy::status>("Status")
139 .class_property("run", &nissy::status::RUN)
140 .class_property("stop", &nissy::status::STOP)
141 .class_property("pause", &nissy::status::PAUSE)
142 ;
143 */
144
145 emscripten::class_<nissy::cube>("Cube")
146 .constructor<>()
147 .function("move", &nissy::cube::move)
148 .function("transform", &nissy::cube::transform)
149 .function("invert", &nissy::cube::invert)
150 .function("toString", &nissy::cube::to_string)
151 ;
152
153 emscripten::class_<nissy::solver::solve_result>("SolveResult")
154 .property("err", &nissy::solver::solve_result::err)
155 .property("solutions", &nissy::solver::solve_result::solutions)
156 ;
157
158 emscripten::function("countMoves", &nissy::count_moves);
159 emscripten::function("solve", &solve,
160 emscripten::return_value_policy::take_ownership());
161 emscripten::function("setLogger", &set_logger,
162 emscripten::allow_raw_pointers());
163 emscripten::function("addCallbackFunction", &addCallbackFunction);
164}

Generated with cgit - Back to sebastiano.tronto.net