feat(web): solver output enhancing
- math render header - tooltips - copy word to input - cancel solver
This commit is contained in:
@@ -14,7 +14,7 @@ stdenv.mkDerivation (finalAttrs: {
|
|||||||
|
|
||||||
yarnOfflineCache = fetchYarnDeps {
|
yarnOfflineCache = fetchYarnDeps {
|
||||||
yarnLock = finalAttrs.src + "/yarn.lock";
|
yarnLock = finalAttrs.src + "/yarn.lock";
|
||||||
hash = "sha256-ND+4leEGamH86IsM9JVtIqlwyrwVRQII75+rrawbiMI=";
|
hash = "sha256-ApqiC2ZS4GzKRXwPCb7KiMO1IemnNU7ykUYlgMp2XjE=";
|
||||||
};
|
};
|
||||||
|
|
||||||
yarnBuildScript = "build-no-wasm";
|
yarnBuildScript = "build-no-wasm";
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.28.2",
|
"esbuild": "^0.28.2",
|
||||||
|
"katex": "^0.18.4",
|
||||||
"rollup": "^4.62.4",
|
"rollup": "^4.62.4",
|
||||||
"svelte": "^5.56.9",
|
"svelte": "^5.56.9",
|
||||||
"wordle-solver": "link:./pkg"
|
"wordle-solver": "link:./pkg"
|
||||||
|
|||||||
+28
-7
@@ -41,7 +41,9 @@
|
|||||||
|
|
||||||
let cursor = $state(0);
|
let cursor = $state(0);
|
||||||
|
|
||||||
function reset() {
|
async function reset() {
|
||||||
|
await solver_reset(use_default_wordle_answers);
|
||||||
|
|
||||||
guesses = [
|
guesses = [
|
||||||
{
|
{
|
||||||
letters: ["", "", "", "", ""],
|
letters: ["", "", "", "", ""],
|
||||||
@@ -59,11 +61,22 @@
|
|||||||
solution_space = solver_solution_space();
|
solution_space = solver_solution_space();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function stopSolver() {
|
||||||
|
await solver_reset(use_default_wordle_answers);
|
||||||
|
for (const g of guesses.slice(0, -1)) {
|
||||||
|
try {
|
||||||
|
await solver_guess(g.letters, g.colors);
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleKey(event: KeyboardEvent) {
|
function handleKey(event: KeyboardEvent) {
|
||||||
if (event.key === "Enter" && event.shiftKey) {
|
if (event.key === "Enter" && event.shiftKey) {
|
||||||
best_words = solver_evaluate_words(5, (p) => {
|
best_words = solver_evaluate_words(5, (p) => {
|
||||||
best_words_progress = p;
|
best_words_progress = p;
|
||||||
});
|
});
|
||||||
|
} else if (event.key === "Escape") {
|
||||||
|
stopSolver();
|
||||||
} else if (event.key === "Enter") {
|
} else if (event.key === "Enter") {
|
||||||
const guess = guesses[guesses.length - 1];
|
const guess = guesses[guesses.length - 1];
|
||||||
|
|
||||||
@@ -107,11 +120,12 @@
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
bind:checked={use_default_wordle_answers}
|
bind:checked={use_default_wordle_answers}
|
||||||
onchange={() => {
|
onfocus={(e) => {
|
||||||
solver_reset(use_default_wordle_answers).then(() => {
|
if (e.currentTarget) {
|
||||||
reset();
|
e.currentTarget.blur();
|
||||||
});
|
}
|
||||||
}}
|
}}
|
||||||
|
onchange={reset}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -141,10 +155,17 @@
|
|||||||
|
|
||||||
<p class="mt-4 text-sm text-zinc-500 mx-auto w-1/2">
|
<p class="mt-4 text-sm text-zinc-500 mx-auto w-1/2">
|
||||||
Type letters · ← → navigate · Space cycle color · Backspace delete ·
|
Type letters · ← → navigate · Space cycle color · Backspace delete ·
|
||||||
Enter apply · Shift+Enter solve
|
Enter apply · Shift+Enter solve · Escape reset
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{#if best_words}
|
{#if best_words}
|
||||||
<SolverOutput data={best_words} progress={best_words_progress} />
|
<SolverOutput
|
||||||
|
data={best_words}
|
||||||
|
progress={best_words_progress}
|
||||||
|
insert_guess={(g) => {
|
||||||
|
console.log("CB");
|
||||||
|
guesses[guesses.length - 1].letters = g;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import katex from "katex";
|
||||||
|
import "katex/dist/katex.min.css";
|
||||||
import type {
|
import type {
|
||||||
EvaluateWordsProgress,
|
EvaluateWordsProgress,
|
||||||
EvaluateWordsResult,
|
EvaluateWordsResult,
|
||||||
@@ -7,10 +9,22 @@
|
|||||||
let {
|
let {
|
||||||
data,
|
data,
|
||||||
progress = null,
|
progress = null,
|
||||||
|
insert_guess = null,
|
||||||
}: {
|
}: {
|
||||||
data: Promise<EvaluateWordsResult>;
|
data: Promise<EvaluateWordsResult>;
|
||||||
progress: EvaluateWordsProgress | null;
|
progress: EvaluateWordsProgress | null;
|
||||||
|
insert_guess: (word: string[]) => void | null;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
|
function renderMath(txt: string | null) {
|
||||||
|
return (element: HTMLElement) => {
|
||||||
|
if (txt) {
|
||||||
|
katex.render(txt, element);
|
||||||
|
} else {
|
||||||
|
katex.render(element.innerText, element);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await data}
|
{#await data}
|
||||||
@@ -27,16 +41,35 @@
|
|||||||
<table class="w-full text-left text-sm text-gray-700">
|
<table class="w-full text-left text-sm text-gray-700">
|
||||||
<thead class="bg-gray-800 text-xs uppercase text-gray-600">
|
<thead class="bg-gray-800 text-xs uppercase text-gray-600">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-4 py-3">Word</th>
|
<th class="px-4 py-3" title="The best words">Word</th>
|
||||||
<th class="px-4 py-3">p[solution]</th>
|
<th
|
||||||
<th class="px-4 py-3">E[Inf.]</th>
|
class="px-4 py-3 math-header"
|
||||||
<th class="px-4 py-3">E[Score]</th>
|
title="The probability that this word is the solution."
|
||||||
|
{@attach renderMath("p(x=\\text{word})")}
|
||||||
|
></th>
|
||||||
|
<th
|
||||||
|
title="The expected information to gain when guessing this word."
|
||||||
|
class="px-4 py-3 math-header"
|
||||||
|
{@attach renderMath("E[\\text{Inf.}]")}
|
||||||
|
></th>
|
||||||
|
<th
|
||||||
|
title="The expected number of guesses for this wordle when guessing this word."
|
||||||
|
class="px-4 py-3 math-header"
|
||||||
|
{@attach renderMath("E[\\text{Score}]")}
|
||||||
|
></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody class="divide-y divide-gray-500">
|
<tbody class="divide-y divide-gray-500">
|
||||||
{#each d.stats as s}
|
{#each d.stats as s}
|
||||||
<tr class="transition-colors hover:bg-gray-50">
|
<tr
|
||||||
|
class="transition-colors hover:bg-gray-50"
|
||||||
|
onclick={() => {
|
||||||
|
if (insert_guess) {
|
||||||
|
insert_guess([...s.word]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<td class="px-4 py-3 font-bold">{s.word}</td>
|
<td class="px-4 py-3 font-bold">{s.word}</td>
|
||||||
<td class="px-4 py-3"
|
<td class="px-4 py-3"
|
||||||
>{s.solution_probability.toFixed(3)}</td
|
>{s.solution_probability.toFixed(3)}</td
|
||||||
@@ -57,3 +90,13 @@
|
|||||||
{e}
|
{e}
|
||||||
</div>
|
</div>
|
||||||
{/await}
|
{/await}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.math-header :global(.katex) {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.math-header :global(.katex .mord) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -69,6 +69,13 @@
|
|||||||
class:bg-green-600={colors[i] === Color.GREEN}
|
class:bg-green-600={colors[i] === Color.GREEN}
|
||||||
class:bg-yellow-600={colors[i] === Color.YELLOW}
|
class:bg-yellow-600={colors[i] === Color.YELLOW}
|
||||||
class:bg-grey-600={colors[i] === Color.GREY}
|
class:bg-grey-600={colors[i] === Color.GREY}
|
||||||
|
onclick={() => {
|
||||||
|
if (cursor === i) {
|
||||||
|
colors[cursor] = (colors[cursor] + 1) % 3;
|
||||||
|
} else {
|
||||||
|
cursor = i;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{letter}
|
{letter}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -767,6 +767,11 @@ color-name@1.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||||
|
|
||||||
|
commander@^8.3.0:
|
||||||
|
version "8.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||||
|
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
@@ -1385,6 +1390,13 @@ json-parse-better-errors@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||||
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
|
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
|
||||||
|
|
||||||
|
katex@^0.18.4:
|
||||||
|
version "0.18.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/katex/-/katex-0.18.4.tgz#aa09d0bfbcbab71a9a0f9d420def6c0d0a227a94"
|
||||||
|
integrity sha512-IMPntbRLOU+eu88XDiFKqQ8Akhr9Tv7jDMXqPhjG9SI1JMA4DIgXk4x9k4skJz2NZJXBRbC+2pYBLj9olqcZow==
|
||||||
|
dependencies:
|
||||||
|
commander "^8.3.0"
|
||||||
|
|
||||||
lightningcss-android-arm64@1.32.0:
|
lightningcss-android-arm64@1.32.0:
|
||||||
version "1.32.0"
|
version "1.32.0"
|
||||||
resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz#f033885116dfefd9c6f54787523e3514b61e1968"
|
resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz#f033885116dfefd9c6f54787523e3514b61e1968"
|
||||||
|
|||||||
Reference in New Issue
Block a user