feat(web): optional wordle-answers

This commit is contained in:
2026-08-21 17:57:45 +02:00
parent 87dfa0c142
commit 539534ad90
5 changed files with 137 additions and 18 deletions
+10 -3
View File
@@ -48,12 +48,19 @@ impl WordStats {
#[allow(dead_code)]
#[wasm_bindgen]
impl Solver {
pub fn new() -> Result<Solver, String> {
pub fn new(use_wordle_answers: bool) -> Result<Solver, String> {
let valid_words =
WordList::try_from(io::BufReader::new(io::Cursor::new(DEFAULT_VALID_WORDS)))?;
let answers = WordList::try_from(io::BufReader::new(io::Cursor::new(DEFAULT_ANSWERS)))?;
Ok(Solver(solver::Solver::new(valid_words, answers)))
if use_wordle_answers {
let answers = WordList::try_from(io::BufReader::new(io::Cursor::new(DEFAULT_ANSWERS)))?;
Ok(Solver(solver::Solver::new(valid_words, answers)))
} else {
Ok(Solver(solver::Solver::new(
valid_words.clone(),
valid_words,
)))
}
}
pub fn guess(&mut self, word: &str, colors: Vec<Color>) -> Result<(), String> {
+37 -4
View File
@@ -4,6 +4,7 @@
import {
solver_evaluate_words,
solver_guess,
solver_reset,
solver_solution_space,
} from "./solver/solver.ts";
import type {
@@ -29,18 +30,35 @@
let infos_gained: (Promise<GuessResult> | null)[] = $state([null]);
let use_default_wordle_answers: boolean = $state(true);
let solution_space: Promise<SolutionSpaceResult> = $state(
solver_solution_space(),
);
self.setTimeout(() => {
solution_space = solver_solution_space();
}, 300);
let best_words: Promise<EvaluateWordsResult> | null = $state(null);
let best_words_progress: EvaluateWordsProgress | null = $state(null);
let cursor = $state(0);
function reset() {
guesses = [
{
letters: ["", "", "", "", ""],
colors: [
Color.GREY,
Color.GREY,
Color.GREY,
Color.GREY,
Color.GREY,
],
},
];
infos_gained = [null];
best_words = null;
solution_space = solver_solution_space();
}
function handleKey(event: KeyboardEvent) {
if (event.key === "Enter" && event.shiftKey) {
best_words = solver_evaluate_words(5, (p) => {
@@ -85,7 +103,22 @@
<h1 class="mb-6 text-3xl font-bold">Wordle Solver</h1>
<p class="mt-4 text-sm text-zinc-500">
{#await solution_space then s}
Use Wordle-Answers:
<input
type="checkbox"
bind:checked={use_default_wordle_answers}
onchange={() => {
solver_reset(use_default_wordle_answers).then(() => {
reset();
});
}}
/>
</p>
<p class="mt-2 text-sm text-zinc-500">
{#await solution_space}
loading
{:then s}
Solution-space: {s.size}, Uncertainty: {s.uncertainty.toFixed(
2,
)}bits
+56 -6
View File
@@ -3,6 +3,7 @@ import SolverWorker from "./worker?worker";
import type { GuessResult, SolutionSpaceResult, EvaluateWordsResult, SolverRequest, SolverResponse, EvaluateWordsProgress } from "./types";
let solver_worker = new SolverWorker();
await init_solver();
let msg_id = 0;
@@ -13,6 +14,25 @@ const pending = new Map<number, {
const progresses = new Map<number, (p: EvaluateWordsProgress) => void>();
function init_solver(): Promise<void> {
return new Promise((resolve) => {
solver_worker.onmessage = (event: any) => {
if (event.data.type === "ready") {
solver_worker.onmessage = workerHandleMsg;
resolve();
} else {
workerHandleMsg(event);
}
};
});
}
function create_solver_worker(): Promise<void> {
solver_worker = new SolverWorker();
return init_solver();
}
export function solver_guess(word: string[], colors: Color[]): Promise<GuessResult> {
const id = msg_id++;
@@ -47,11 +67,11 @@ export function solver_solution_space(): Promise<SolutionSpaceResult> {
export function solver_evaluate_words(n: number, progress: ((p: EvaluateWordsProgress) => void) | null): Promise<EvaluateWordsResult> {
const id = msg_id++;
if (progress) {
progresses.set(id, progress);
}
return new Promise((resolve, reject) => {
pending.set(id, { resolve, reject });
@@ -65,13 +85,40 @@ export function solver_evaluate_words(n: number, progress: ((p: EvaluateWordsPro
});
}
export async function solver_reset(wordle_answers: boolean): Promise<void> {
solver_worker.terminate();
solver_worker.onmessage = (event: MessageEvent<SolverResponse>) => {
await create_solver_worker();
console.log("Created: ans=" + wordle_answers);
pending.forEach((v, _) => {
v.reject("Solver was reset");
});
pending.clear();
progresses.clear();
const id = msg_id++;
return new Promise((resolve, reject) => {
pending.set(id, { resolve, reject });
const r: SolverRequest = {
type: "reload_wordlist",
id: id,
input: { use_wordle_ansers: wordle_answers },
};
solver_worker.postMessage(JSON.parse(JSON.stringify(r)));
});
}
function workerHandleMsg(event: MessageEvent<SolverResponse>) {
let res = event.data;
if (res.type == "evaluate_words_progress") {
let progress = progresses.get(res.id);
if (progress) {
progress(res.result);
}
@@ -79,6 +126,8 @@ solver_worker.onmessage = (event: MessageEvent<SolverResponse>) => {
return;
}
console.log("Rcv msg: ", res.type + " " + res.id);
const pendingRequest = pending.get(res.id);
if (!pendingRequest) {
@@ -95,4 +144,5 @@ solver_worker.onmessage = (event: MessageEvent<SolverResponse>) => {
} else {
pendingRequest.reject("No result");
}
};
}
+15
View File
@@ -15,6 +15,11 @@ export type SolverRequest =
type: "solution_space",
id: number,
input: null,
}
| {
type: "reload_wordlist",
id: number,
input: ReloadWordlist
};
export type SolverResponse =
@@ -33,6 +38,7 @@ export type SolverResponse =
| {
type: "evaluate_words_progress",
id: number,
error: null,
result: EvaluateWordsProgress
}
| {
@@ -40,6 +46,12 @@ export type SolverResponse =
id: number,
error: string | null,
result: SolutionSpaceResult | null
}
| {
type: "reload_wordlist",
id: number,
error: string | null
result: boolean | null,
};
export type Guess = {
@@ -56,6 +68,9 @@ export type EvaluateWordsProgress = {
i: number,
n: number
};
export type ReloadWordlist = {
use_wordle_ansers: boolean
};
export type WordStats = {
word: string,
solution_probability: number,
+19 -5
View File
@@ -1,7 +1,11 @@
import { Solver, } from "wordle-solver";
import type { SolverRequest, SolverResponse, WordStats } from "./types";
let solver = Solver.new();
let solver = Solver.new(true);
self.postMessage({
type: "ready",
});
self.onmessage = (event: MessageEvent<SolverRequest>) => {
const request = event.data;
@@ -40,6 +44,7 @@ self.onmessage = (event: MessageEvent<SolverRequest>) => {
let p: SolverResponse = {
type: "evaluate_words_progress",
id: request.id,
error: null,
result: { i, n }
};
self.postMessage(JSON.parse(JSON.stringify(p)));
@@ -77,10 +82,19 @@ self.onmessage = (event: MessageEvent<SolverRequest>) => {
type: "solution_space",
id: request.id,
error: null,
result: {
size: solver.solution_space(),
uncertainty: solver.solution_space_uncertainty()
}
result: { size: solver.solution_space(), uncertainty: solver.solution_space_uncertainty() }
};
self.postMessage(JSON.parse(JSON.stringify(response)));
break;
};
case "reload_wordlist": {
solver.free();
solver = Solver.new(request.input.use_wordle_ansers);
const response: SolverResponse = {
type: "reload_wordlist",
id: request.id,
error: null,
result: true
};
self.postMessage(JSON.parse(JSON.stringify(response)));
break;