diff options
Diffstat (limited to 'web/http')
| -rw-r--r-- | web/http/index.html | 21 | ||||
| -rw-r--r-- | web/http/nissyapp.mjs | 134 |
2 files changed, 145 insertions, 10 deletions
diff --git a/web/http/index.html b/web/http/index.html index c80f7ec..0846ea8 100644 --- a/web/http/index.html +++ b/web/http/index.html | |||
| @@ -9,12 +9,27 @@ | |||
| 9 | <body> | 9 | <body> |
| 10 | <input id="scrambleText" placeholder="Type the scramble here..."> | 10 | <input id="scrambleText" placeholder="Type the scramble here..."> |
| 11 | <select id="solverSelector"> | 11 | <select id="solverSelector"> |
| 12 | <option value="h48h0k4" selected="selected">h48 h=0 k=4 (59Mb)</option> | 12 | <option value="h48h0k4">h48 h=0 k=4 (59Mb)</option> |
| 13 | <option value="h48h3k2">h48 h=3 k=2 (283Mb)</option> | 13 | <option value="h48h3k2" selected="selected">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 | <div id="confirmDownload" style="display:none"> | ||
| 18 | <p id="confirmDownloadText"> | ||
| 19 | For this solver to work, a large data table is required. | ||
| 20 | You can either download it or generate it locally. | ||
| 21 | </p> | ||
| 22 | <p id="confirmDownloadExtraText"> | ||
| 23 | In either case, this data will be stored locally for future use. You | ||
| 24 | can delete it at any time by clearing your browser's data. | ||
| 25 | </p> | ||
| 26 | <button id="confirmDownloadCancel">Cancel</button> | ||
| 27 | <button id="confirmDownloadConfirm">Download</button> | ||
| 28 | <button id="confirmDownloadGenerate">Generate locally</button> | ||
| 29 | </div> | ||
| 17 | <p id="resultsLabel"></p> | 30 | <p id="resultsLabel"></p> |
| 18 | <p id="results"></p> | 31 | <p id="results"></p> |
| 32 | <button id="toggleShowLog">Show nissy log messages</button> | ||
| 33 | <p id="logPane" style="display:none"></p> | ||
| 19 | </body> | 34 | </body> |
| 20 | </html> | 35 | </html> |
diff --git a/web/http/nissyapp.mjs b/web/http/nissyapp.mjs index 23e74d0..b8a525c 100644 --- a/web/http/nissyapp.mjs +++ b/web/http/nissyapp.mjs | |||
| @@ -7,30 +7,149 @@ var scrField = document.getElementById("scrambleText"); | |||
| 7 | var resultsLabel = document.getElementById("resultsLabel"); | 7 | var resultsLabel = document.getElementById("resultsLabel"); |
| 8 | var resultsText = document.getElementById("results"); | 8 | var resultsText = document.getElementById("results"); |
| 9 | var solverSelector = document.getElementById("solverSelector"); | 9 | var solverSelector = document.getElementById("solverSelector"); |
| 10 | var toggleLog = document.getElementById("toggleShowLog"); | ||
| 11 | var logPane = document.getElementById("logPane"); | ||
| 10 | 12 | ||
| 11 | var lastCallbackId = 0; | 13 | var lastCallbackId = 0; |
| 12 | var callbacks = new Map(); // Values: { f: function, arg: object } | 14 | var callbacks = new Map(); // Values: { f: function, arg: object } |
| 13 | var worker = new Worker("./worker.mjs", { type: "module" }); | 15 | var worker = new Worker("./worker.mjs", { type: "module" }); |
| 14 | worker.onmessage = (event) => { | 16 | worker.onmessage = (event) => { |
| 15 | if (event.data.command == "log") { | 17 | if (event.data.command == "log") { |
| 16 | console.log(event.data.object); // TODO | 18 | logPane.innerText += event.data.object; |
| 19 | console.log(event.data.object); | ||
| 17 | } else if (!callbacks.has(event.data.id)) { | 20 | } else if (!callbacks.has(event.data.id)) { |
| 18 | console.log("[nissy app] Unknown callback " + event.data.id + | 21 | console.log("[nissy app] Unknown callback " + event.data.id + |
| 19 | " for command " + event.data.command); | 22 | " for command " + event.data.command); |
| 20 | } else { | 23 | } else { |
| 21 | var callback = callbacks.get(event.data.id); | 24 | var callback = callbacks.get(event.data.id); |
| 25 | callbacks.delete(event.data.id); | ||
| 22 | callback.f(callback.arg, event.data.arg); | 26 | callback.f(callback.arg, event.data.arg); |
| 23 | } | 27 | } |
| 24 | }; | 28 | }; |
| 25 | 29 | ||
| 26 | function updateResults(label, results, buttonState) { | 30 | function updateResults(label, results, enable) { |
| 27 | resultsLabel.innerText = label; | 31 | resultsLabel.innerText = label; |
| 28 | resultsText.innerText = results; | 32 | resultsText.innerText = results; |
| 29 | solveButton.disable = !buttonState; | 33 | solveButton.disable = !enable; |
| 34 | solverSelector.disable = !enable; | ||
| 30 | } | 35 | } |
| 31 | 36 | ||
| 37 | var logVisible = false; | ||
| 38 | toggleLog.addEventListener("click", () => { | ||
| 39 | logVisible = !logVisible; | ||
| 40 | if (logVisible) { | ||
| 41 | logPane.style.display = "block"; | ||
| 42 | toggleLog.innerText = "Hide nissy log messages"; | ||
| 43 | } else { | ||
| 44 | logPane.style.display = "none"; | ||
| 45 | toggleLog.innerText = "Show nissy log messages"; | ||
| 46 | } | ||
| 47 | }); | ||
| 48 | |||
| 32 | solveButton.addEventListener("click", () => { | 49 | solveButton.addEventListener("click", () => { |
| 33 | updateResults("Loading solutions...", "", false); | 50 | const solver = solverSelector.options[solverSelector.selectedIndex].value; |
| 51 | const scramble = scrField.value; | ||
| 52 | loadDataThenSolve(solver, scramble); | ||
| 53 | |||
| 54 | const solveCallbackId = ++lastCallbackId; | ||
| 55 | callbacks.set(solveCallbackId, { | ||
| 56 | f: (callbackArg, loadResult) => { | ||
| 57 | if (loadResult.success) { | ||
| 58 | startSolve(callbackArg.solver, callbackArg.scramble); | ||
| 59 | } else { | ||
| 60 | updateResults("", "", true); | ||
| 61 | } | ||
| 62 | }, | ||
| 63 | arg: { solver: solver, scramble: scramble } | ||
| 64 | }); | ||
| 65 | |||
| 66 | const downloadCallbackId = ++lastCallbackId; | ||
| 67 | }); | ||
| 68 | |||
| 69 | function loadDataThenSolve(solver, scramble) { | ||
| 70 | updateResults("Loading solver " + solver + "...", "", false); | ||
| 71 | |||
| 72 | const callbackId = ++lastCallbackId; | ||
| 73 | callbacks.set(callbackId, { | ||
| 74 | f: (callbackArg, loadResult) => { | ||
| 75 | if (loadResult.success) | ||
| 76 | startSolve(callbackArg.solver, callbackArg.scramble); | ||
| 77 | else | ||
| 78 | askDownloadThenSolve(callbackArg.solver, callbackArg.scramble); | ||
| 79 | }, | ||
| 80 | arg: { solver: solver, scramble: scramble } | ||
| 81 | }); | ||
| 82 | |||
| 83 | worker.postMessage({ | ||
| 84 | command: "load solver data", | ||
| 85 | id: callbackId, | ||
| 86 | arg: solver | ||
| 87 | }); | ||
| 88 | } | ||
| 89 | |||
| 90 | function askDownloadThenSolve(solver, scramble) { | ||
| 91 | var confirmDiv = document.getElementById("confirmDownload"); | ||
| 92 | var cancel = document.getElementById("confirmDownloadCancel"); | ||
| 93 | var download = document.getElementById("confirmDownloadConfirm"); | ||
| 94 | var generate = document.getElementById("confirmDownloadGenerate"); | ||
| 95 | const cleanup = () => { | ||
| 96 | confirmDiv.style.display = "none"; | ||
| 97 | |||
| 98 | // Remove event listeners by cloning the buttons | ||
| 99 | cancel.outerHTML = cancel.outerHTML; | ||
| 100 | download.outerHTML = download.outerHTML; | ||
| 101 | generate.outerHTML = generate.outerHTML; | ||
| 102 | }; | ||
| 103 | |||
| 104 | updateResults("", "", false); | ||
| 105 | confirmDiv.style.display = "block"; | ||
| 106 | |||
| 107 | cancel.addEventListener("click", cleanup); | ||
| 108 | |||
| 109 | download.addEventListener("click", () => { | ||
| 110 | cleanup(); | ||
| 111 | downloadDataThenSolve(solver, scramble); | ||
| 112 | }); | ||
| 113 | |||
| 114 | generate.addEventListener("click", () => { | ||
| 115 | cleanup(); | ||
| 116 | generateDataThenSolve(solver, scramble); | ||
| 117 | }); | ||
| 118 | } | ||
| 119 | |||
| 120 | const downloadDataThenSolve = (solver, scramble) => | ||
| 121 | downloadOrGenerateThenSolve(solver, scramble, true); | ||
| 122 | |||
| 123 | const generateDataThenSolve = (solver, scramble) => | ||
| 124 | downloadOrGenerateThenSolve(solver, scramble, false); | ||
| 125 | |||
| 126 | function downloadOrGenerateThenSolve(solver, scramble, download) { | ||
| 127 | const msg = download ? "Downloading data for " : "Generating data for "; | ||
| 128 | const command = download ? "download solver data" : "generate solver data"; | ||
| 129 | |||
| 130 | updateResults(msg + solver + "...", "", false); | ||
| 131 | |||
| 132 | const callbackId = ++lastCallbackId; | ||
| 133 | callbacks.set(callbackId, { | ||
| 134 | f: (callbackArg, loadResult) => { | ||
| 135 | if (loadResult.success) | ||
| 136 | startSolve(callbackArg.solver, callbackArg.scramble); | ||
| 137 | else | ||
| 138 | updateResults("Failed", loadResult.message, true); | ||
| 139 | }, | ||
| 140 | arg: { solver: solver, scramble: scramble } | ||
| 141 | }); | ||
| 142 | |||
| 143 | worker.postMessage({ | ||
| 144 | command: command, | ||
| 145 | id: callbackId, | ||
| 146 | arg: solver | ||
| 147 | }); | ||
| 148 | } | ||
| 149 | |||
| 150 | function startSolve(solver, scramble) { | ||
| 151 | updateResults("Solving...", "", false); | ||
| 152 | |||
| 34 | const callbackId = ++lastCallbackId; | 153 | const callbackId = ++lastCallbackId; |
| 35 | callbacks.set(callbackId, { | 154 | callbacks.set(callbackId, { |
| 36 | f: (callbackArg, solveResult) => { | 155 | f: (callbackArg, solveResult) => { |
| @@ -46,12 +165,13 @@ solveButton.addEventListener("click", () => { | |||
| 46 | }, | 165 | }, |
| 47 | arg: "" // Currently unused | 166 | arg: "" // Currently unused |
| 48 | }); | 167 | }); |
| 168 | |||
| 49 | worker.postMessage({ | 169 | worker.postMessage({ |
| 50 | command: "solve", | 170 | command: "solve", |
| 51 | id: callbackId, | 171 | id: callbackId, |
| 52 | arg: { | 172 | arg: { |
| 53 | solver: solverSelector.options[solverSelector.selectedIndex].value, | 173 | solver: solver, |
| 54 | scramble: scrField.value, | 174 | scramble: scramble, |
| 55 | minmoves: 0, | 175 | minmoves: 0, |
| 56 | maxmoves: 20, | 176 | maxmoves: 20, |
| 57 | maxsolutions: 1, | 177 | maxsolutions: 1, |
| @@ -59,4 +179,4 @@ solveButton.addEventListener("click", () => { | |||
| 59 | threads: window.navigator.hardwareConcurrency, | 179 | threads: window.navigator.hardwareConcurrency, |
| 60 | } | 180 | } |
| 61 | }); | 181 | }); |
| 62 | }); | 182 | } |
