aboutsummaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/http/index.html8
-rw-r--r--web/http/nissyapp.mjs62
-rw-r--r--web/http/solve.mjs33
-rw-r--r--web/http/worker.mjs27
-rw-r--r--web/worker.mjs114
5 files changed, 180 insertions, 64 deletions
diff --git a/web/http/index.html b/web/http/index.html
index 245205d..c80f7ec 100644
--- a/web/http/index.html
+++ b/web/http/index.html
@@ -4,7 +4,7 @@
4 <meta charset="utf-8" /> 4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width" /> 5 <meta name="viewport" content="width=device-width" />
6 <title>Nissy - H48 solver POC</title> 6 <title>Nissy - H48 solver POC</title>
7 <script type="module" src="./solve.mjs"></script> 7 <script type="module" src="./nissyapp.mjs"></script>
8 </head> 8 </head>
9 <body> 9 <body>
10 <input id="scrambleText" placeholder="Type the scramble here..."> 10 <input id="scrambleText" placeholder="Type the scramble here...">
@@ -13,8 +13,8 @@
13 <option value="h48h3k2">h48 h=3 k=2 (283Mb)</option> 13 <option value="h48h3k2">h48 h=3 k=2 (283Mb)</option>
14 <option value="h48h7k2">h48 h=7 k=2 (3.6Gb)</option> 14 <option value="h48h7k2">h48 h=7 k=2 (3.6Gb)</option>
15 </select> 15 </select>
16 <button id="solveButton">Solve!</button> 16 <button id="solveButton">Solve</button>
17 <p>Solution:</p> 17 <p id="resultsLabel"></p>
18 <p id="solution"></p> 18 <p id="results"></p>
19 </body> 19 </body>
20</html> 20</html>
diff --git a/web/http/nissyapp.mjs b/web/http/nissyapp.mjs
new file mode 100644
index 0000000..23e74d0
--- /dev/null
+++ b/web/http/nissyapp.mjs
@@ -0,0 +1,62 @@
1// Run ./build web from the main folder before running this example.
2// The necessary modules (including worker.mjs) will be built and / or moved
3// to this folder when running ./build web.
4
5var solveButton = document.getElementById("solveButton");
6var scrField = document.getElementById("scrambleText");
7var resultsLabel = document.getElementById("resultsLabel");
8var resultsText = document.getElementById("results");
9var solverSelector = document.getElementById("solverSelector");
10
11var lastCallbackId = 0;
12var callbacks = new Map(); // Values: { f: function, arg: object }
13var worker = new Worker("./worker.mjs", { type: "module" });
14worker.onmessage = (event) => {
15 if (event.data.command == "log") {
16 console.log(event.data.object); // TODO
17 } else if (!callbacks.has(event.data.id)) {
18 console.log("[nissy app] Unknown callback " + event.data.id +
19 " for command " + event.data.command);
20 } else {
21 var callback = callbacks.get(event.data.id);
22 callback.f(callback.arg, event.data.arg);
23 }
24};
25
26function updateResults(label, results, buttonState) {
27 resultsLabel.innerText = label;
28 resultsText.innerText = results;
29 solveButton.disable = !buttonState;
30}
31
32solveButton.addEventListener("click", () => {
33 updateResults("Loading solutions...", "", false);
34 const callbackId = ++lastCallbackId;
35 callbacks.set(callbackId, {
36 f: (callbackArg, solveResult) => {
37 if (solveResult.success) {
38 const n = solveResult.solutions.length;
39 const label = n == 0 ? "No solution found" :
40 ("Found " + n + " solution" + (n == 1 ? "" : "s")) + ":";
41 const text = solveResult.solutions.join("\n");
42 updateResults(label, text, true);
43 } else {
44 updateResults("Unexpected error while solving!", "", true);
45 }
46 },
47 arg: "" // Currently unused
48 });
49 worker.postMessage({
50 command: "solve",
51 id: callbackId,
52 arg: {
53 solver: solverSelector.options[solverSelector.selectedIndex].value,
54 scramble: scrField.value,
55 minmoves: 0,
56 maxmoves: 20,
57 maxsolutions: 1,
58 optimal: 20,
59 threads: window.navigator.hardwareConcurrency,
60 }
61 });
62});
diff --git a/web/http/solve.mjs b/web/http/solve.mjs
deleted file mode 100644
index 127e1e3..0000000
--- a/web/http/solve.mjs
+++ /dev/null
@@ -1,33 +0,0 @@
1var solveButton = document.getElementById("solveButton");
2var scrField = document.getElementById("scrambleText");
3var solutionText = document.getElementById("solution");
4var solverSelector = document.getElementById("solverSelector");
5
6var worker = new Worker("./worker.mjs", { type: "module" });
7worker.onmessage = (e) => {
8 updateResults(e.data);
9 enableSolveButton();
10};
11
12function updateResults(s) {
13 solutionText.innerText = s;
14}
15
16function disableSolveButton() {
17 solveButton.disabled = true;
18 solveButton.innerText = "Solving...";
19}
20
21function enableSolveButton() {
22 solveButton.disabled = false;
23 solveButton.innerText = "Solve!";
24}
25
26solveButton.addEventListener("click", () => {
27 disableSolveButton();
28 updateResults("Loading solutions...");
29 worker.postMessage({
30 solver: solverSelector.options[solverSelector.selectedIndex].value,
31 scramble: scrField.value
32 });
33});
diff --git a/web/http/worker.mjs b/web/http/worker.mjs
deleted file mode 100644
index 7ce1070..0000000
--- a/web/http/worker.mjs
+++ /dev/null
@@ -1,27 +0,0 @@
1import Nissy from "./nissy_web_module.mjs"
2
3const nissy = await Nissy();
4nissy.setLogger(nissy._addCallbackFunction(console.log));
5
6onmessage = (e) => {
7//TODO: try to load from storage first, then download
8 nissy.initSolverDownload(e.data.solver, "/tables").then(
9 (download_result) => {
10 if (!download_result) {
11 postMessage("Error retrieving the solver data");
12 } else {
13 var cube = new nissy.Cube();
14 cube.move(e.data.scramble);
15
16 nissy.solve(e.data.solver, cube, nissy.NissFlag.normal,
17 0, 17, 1, 99, 4, -1).then(
18 (solve_result) => {
19 if (!solve_result.err.ok())
20 postMessage("Error while solving (solve returned " +
21 solve_result.err.value + ")");
22 else
23 postMessage(solve_result.solutions)
24 });
25 }
26 });
27};
diff --git a/web/worker.mjs b/web/worker.mjs
new file mode 100644
index 0000000..dca980e
--- /dev/null
+++ b/web/worker.mjs
@@ -0,0 +1,114 @@
1import Nissy from "./nissy_web_module.mjs"
2
3const nissy = await Nissy();
4function log(message) {
5 postMessage({ command: "log", id: -1, object: message });
6 console.log(message);
7}
8nissy.setLogger(nissy._addCallbackFunction(log));
9
10const commands = [
11 { name: "solve", exec: solve },
12 { name: "download solver data", exec: downloadSolverData },
13];
14
15// Message structure:
16// {
17// command: string // The function to run.
18// id: number // An identification number for the command, used for
19// // sending responses back to the caller and having them
20// // caught by the correct handler.
21// arg: object // The actual argument of the message, command-specific.
22// // See below for details.
23// }
24onmessage = (event) => {
25 for (var i = 0; i < commands.length; i++) {
26 if (commands[i].name == event.data.command) {
27 commands[i].exec(event.data.id, event.data.arg);
28 return;
29 }
30 }
31
32 log("[nissy worker] unknown command " + event.data.command);
33};
34
35// Download solver data.
36// Argument: string
37async function downloadSolverData(id, solver) {
38 const downloadSolverDataReturn = (success, message = "") => postMessage({
39 command: "download solver data",
40 id: id,
41 arg: {
42 success: success,
43 message: message
44 }
45 });
46
47 if (await nissy.initSolverDownload(arg.solver, "/tables")) {
48 downloadSolverDataReturn(true);
49 } else {
50 downloadSolverDataReturn(false, "Error retrieving the solver data");
51 }
52}
53
54// Solve the cube with the given options.
55// Argument: {
56// solver: string
57// scramble: string
58// minmoves: number
59// maxmoves: number
60// maxsolutions: number
61// optimal: number
62// threads: number
63// }
64async function solve(id, arg) {
65 const solveReturn = (success, solutions = [], message = "") => postMessage({
66 command: "solve",
67 id: id,
68 arg: {
69 success: success,
70 solutions: solutions,
71 message: message
72 }
73 });
74
75 if (!(await nissy.isSolverAvailable(arg.solver))) {
76 solveReturn(false, [], "Error: solver " + arg.solver +
77 " is not available in this version of nissy.");
78 return;
79 }
80
81 if (!(await nissy.isSolverLoaded(arg.solver)) &&
82 !(await nissy.initSolverFromStorage(arg.solver))) {
83 solveReturn(false, [], "Error: solver " + arg.solver + " has not been " +
84 "loaded. Its data must be donwloaded or generated before using it.");
85 return;
86 }
87
88 var cube = new nissy.Cube();
89 cube.move(arg.scramble);
90
91 // TODO: error handling here?
92 const nissFlag = ((str) => {
93 switch (str) {
94 case "inverse": return nissy.NissFlag.inverse;
95 case "mixed": return nissy.NissFlag.mixed;
96 case "linear": return nissy.NissFlag.linear;
97 case "all": return nissy.NissFlag.all;
98 default: return nissy.NissFlag.normal;
99 }
100 })(arg.nissFlag);
101
102 const result = await nissy.solve(arg.solver, cube, nissFlag, arg.minmoves,
103 arg.maxmoves, arg.maxsolutions, arg.optimal, arg.threads, id);
104
105 if (result.err.ok()) {
106 //TODO: add solution lenght?
107 var solutions = result.solutions == "" ? [] : result.solutions.split("\n");
108 solutions.pop(); // Solver always returns string ending in newline
109 solveReturn(true, solutions);
110 } else {
111 solveReturn(false, [],
112 "Error while solving (error " + result.err.value + ")");
113 }
114};

Generated with cgit - Back to sebastiano.tronto.net