From fa0fa1fcb494483020a736a2bc2c5c639a2bd870 Mon Sep 17 00:00:00 2001 From: Sebastiano Tronto Date: Mon, 26 May 2025 17:05:36 +0200 Subject: Progress with web version --- web/adapter.cpp | 179 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 117 insertions(+), 62 deletions(-) (limited to 'web/adapter.cpp') diff --git a/web/adapter.cpp b/web/adapter.cpp index 71a34ab..676390c 100644 --- a/web/adapter.cpp +++ b/web/adapter.cpp @@ -1,5 +1,12 @@ +extern "C" { + extern int addCallbackFunction(/* args intentionally unspecified */); + extern void callFunction(int, const char *); + extern int callFunctionInt(int); +} + #include "../cpp/nissy.h" #include "storage.h" +#include "logging.h" #include #include @@ -10,78 +17,130 @@ EM_ASYNC_JS(void, fake_async, (), {}); -extern "C" { - extern int addCallbackFunction(/* args intentionally unspecified */); - extern void callFunction(int, const char *); - extern int callFunctionInt(int); +const std::set available_solvers +{ + "h48h0k4", + "h48h1k2", + "h48h2k2", + "h48h3k2", + "h48h7k2", +}; + +std::map loaded_solvers; + +bool is_solver_available(const std::string& name) +{ + return available_solvers.contains(name); } -static int logger_id = -1; +bool is_solver_loaded(const std::string& name) +{ + return loaded_solvers.contains(name); +} -void log(std::string s) +bool check_data(nissy::solver& solver) { - if (logger_id == -1) - return; + log("Checking data integrity " + "(this is done only once per session per solver)...\n"); + + if (!solver.check_data().ok()) { + log("Error! Data is corrupted!\n"); + return false; + } - callFunction(logger_id, s.c_str()); + return true; } -void log_wrapper(const char *cstr, void *data) +bool read_solver_data(nissy::solver& solver) { - log(cstr); + solver.data.resize(solver.size); + + bool success = storage::read(solver.id, solver.size, + reinterpret_cast(solver.data.data())); + + if (!success) { + log("Could not read data for solver " + + solver.name + " from storage\n"); + return false; + } + + if (!check_data(solver)) { + log("Data for solver " + solver.name + " is corrupt!\n"); + return false; + } + + log("Data for solver " + solver.name + " read from storage\n"); + loaded_solvers.insert({solver.name, solver}); + + return true; } -void set_logger(int id) +bool is_solver_valid(const std::string& name, + std::variant& se) { - logger_id = id; - nissy::set_logger(log_wrapper, NULL); + if (std::holds_alternative(se)) { + log("Invalid solver " + name + "\n"); + return false; + } + + if (!is_solver_available(name)) { + log("Solver " + name + " is not available in this version\n"); + return false; + } + + return true; } -// Some of the solvers are not available to the JS interface because of -// memory limitations. -const std::set available_solvers +bool init_solver_from_storage(const std::string& name) { - "h48h0k4", - "h48h1k2", - "h48h2k2", - "h48h3k2", - "h48h7k2", -}; + if (is_solver_loaded(name)) + return true; + auto se = nissy::solver::get(name); + if (!is_solver_valid(name, se)) + return false; + nissy::solver solver = std::get(se); -std::map loaded_solvers; + return read_solver_data(solver); +} -// TODO: this should ask the user if they want to download or generate. -bool init_solver(const std::string& name) +bool init_solver_download(const std::string& name, const std::string& urlbase) { + if (is_solver_loaded(name)) + return true; auto se = nissy::solver::get(name); + if (!is_solver_valid(name, se)) + return false; nissy::solver solver = std::get(se); - solver.data.resize(solver.size); - if (storage::read(solver.id, solver.size, - reinterpret_cast(solver.data.data()))) { - log("Data for solver " + solver.name + " read from storage\n"); + if (storage::download(solver.id, urlbase + "/" + solver.id)) { + return read_solver_data(solver); } else { - log("Could not read data for solver " + solver.name + - " from storage, generating it\n"); - auto err = solver.generate_data(); - - if (!err.ok()) { - log("Error generating the data!\n"); - return false; - } + return false; } +} - log("Checking data integrity " - "(this is done only once per session per solver)...\n"); - if (!solver.check_data().ok()) { - log("Error! Data is corrupted!\n"); +bool init_solver_generate(const std::string& name) +{ + if (is_solver_loaded(name)) + return true; + auto se = nissy::solver::get(name); + if (!is_solver_valid(name, se)) + return false; + nissy::solver solver = std::get(se); + + if (!solver.generate_data().ok()) { + log("Error generating data for solver " + name + "!\n"); + return false; + } + + if (!check_data(solver)) { + log("Data for solver " + name + " generated incorrectly!\n"); return false; } - loaded_solvers.insert({name, solver}); if (storage::write(solver.id, solver.size, reinterpret_cast(solver.data.data()))) { - log("Data for solver " + solver.name + " stored\n"); + log("Data for solver " + name + " stored\n"); } else { log("Error storing the data (the solver is usable, " "but the data will have to be re-generated next " @@ -91,21 +150,6 @@ bool init_solver(const std::string& name) return true; } -bool solver_valid(const std::string& name) -{ - if (loaded_solvers.contains(name) || - (available_solvers.contains(name) && init_solver(name))) - return true; - - auto se = nissy::solver::get(name); - if (std::holds_alternative(se)) - log("The solver " + name + " is not available in " - "the web version of Nissy. Use a native version.\n"); - else - log("Invalid solver " + name + "\n"); - return false; -} - int poll_status(void *arg) { if (arg == NULL || *(int *)arg == -1) @@ -127,9 +171,11 @@ nissy::solver::solve_result solve(std::string name, // TODO figure out if there is a better way to do this. fake_async(); - if (!solver_valid(name)) + if (!is_solver_loaded(name)) { + log("Solver " + name + " is invalid or has not been loaded\n"); return nissy::solver::solve_result {.err = nissy::error::INVALID_SOLVER}; + } return loaded_solvers.at(name).solve(cube, nissflag, minmoves, maxmoves, maxsols, optimal, threads, NULL, &poll_status_id); @@ -147,8 +193,10 @@ EMSCRIPTEN_BINDINGS(Nissy) emscripten::class_("Error") .function("ok", &nissy::error::ok) - .class_property("unsolvableWarning", &nissy::error::UNSOLVABLE_WARNING) - .class_property("unsolvableError", &nissy::error::UNSOLVABLE_ERROR) + .class_property("unsolvableWarning", + &nissy::error::UNSOLVABLE_WARNING) + .class_property("unsolvableError", + &nissy::error::UNSOLVABLE_ERROR) .class_property("invalidCube", &nissy::error::INVALID_CUBE) .class_property("invalidMoves", &nissy::error::INVALID_MOVES) .class_property("invalidTrans", &nissy::error::INVALID_TRANS) @@ -182,6 +230,13 @@ EMSCRIPTEN_BINDINGS(Nissy) .property("solutions", &nissy::solver::solve_result::solutions) ; + emscripten::function("isSolverAvailable", &is_solver_available); + emscripten::function("isSolverLoaded", &is_solver_loaded); + emscripten::function("initSolverFromStorage", + &init_solver_from_storage); + emscripten::function("initSolverDownload", &init_solver_download); + emscripten::function("initSolverGenerate", &init_solver_generate); + emscripten::function("countMoves", &nissy::count_moves); emscripten::function("solve", &solve, emscripten::return_value_policy::take_ownership()); -- cgit v1.3