feat(web): optional wordle-answers
This commit is contained in:
+9
-2
@@ -48,12 +48,19 @@ impl WordStats {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
impl Solver {
|
impl Solver {
|
||||||
pub fn new() -> Result<Solver, String> {
|
pub fn new(use_wordle_answers: bool) -> Result<Solver, String> {
|
||||||
let valid_words =
|
let valid_words =
|
||||||
WordList::try_from(io::BufReader::new(io::Cursor::new(DEFAULT_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)))?;
|
|
||||||
|
|
||||||
|
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)))
|
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> {
|
pub fn guess(&mut self, word: &str, colors: Vec<Color>) -> Result<(), String> {
|
||||||
|
|||||||
+37
-4
@@ -4,6 +4,7 @@
|
|||||||
import {
|
import {
|
||||||
solver_evaluate_words,
|
solver_evaluate_words,
|
||||||
solver_guess,
|
solver_guess,
|
||||||
|
solver_reset,
|
||||||
solver_solution_space,
|
solver_solution_space,
|
||||||
} from "./solver/solver.ts";
|
} from "./solver/solver.ts";
|
||||||
import type {
|
import type {
|
||||||
@@ -29,18 +30,35 @@
|
|||||||
|
|
||||||
let infos_gained: (Promise<GuessResult> | null)[] = $state([null]);
|
let infos_gained: (Promise<GuessResult> | null)[] = $state([null]);
|
||||||
|
|
||||||
|
let use_default_wordle_answers: boolean = $state(true);
|
||||||
|
|
||||||
let solution_space: Promise<SolutionSpaceResult> = $state(
|
let solution_space: Promise<SolutionSpaceResult> = $state(
|
||||||
solver_solution_space(),
|
solver_solution_space(),
|
||||||
);
|
);
|
||||||
self.setTimeout(() => {
|
|
||||||
solution_space = solver_solution_space();
|
|
||||||
}, 300);
|
|
||||||
|
|
||||||
let best_words: Promise<EvaluateWordsResult> | null = $state(null);
|
let best_words: Promise<EvaluateWordsResult> | null = $state(null);
|
||||||
let best_words_progress: EvaluateWordsProgress | null = $state(null);
|
let best_words_progress: EvaluateWordsProgress | null = $state(null);
|
||||||
|
|
||||||
let cursor = $state(0);
|
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) {
|
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) => {
|
||||||
@@ -85,7 +103,22 @@
|
|||||||
<h1 class="mb-6 text-3xl font-bold">Wordle Solver</h1>
|
<h1 class="mb-6 text-3xl font-bold">Wordle Solver</h1>
|
||||||
|
|
||||||
<p class="mt-4 text-sm text-zinc-500">
|
<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(
|
Solution-space: {s.size}, Uncertainty: {s.uncertainty.toFixed(
|
||||||
2,
|
2,
|
||||||
)}bits
|
)}bits
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import SolverWorker from "./worker?worker";
|
|||||||
import type { GuessResult, SolutionSpaceResult, EvaluateWordsResult, SolverRequest, SolverResponse, EvaluateWordsProgress } from "./types";
|
import type { GuessResult, SolutionSpaceResult, EvaluateWordsResult, SolverRequest, SolverResponse, EvaluateWordsProgress } from "./types";
|
||||||
|
|
||||||
let solver_worker = new SolverWorker();
|
let solver_worker = new SolverWorker();
|
||||||
|
await init_solver();
|
||||||
|
|
||||||
let msg_id = 0;
|
let msg_id = 0;
|
||||||
|
|
||||||
@@ -13,6 +14,25 @@ const pending = new Map<number, {
|
|||||||
|
|
||||||
const progresses = new Map<number, (p: EvaluateWordsProgress) => void>();
|
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> {
|
export function solver_guess(word: string[], colors: Color[]): Promise<GuessResult> {
|
||||||
const id = msg_id++;
|
const id = msg_id++;
|
||||||
|
|
||||||
@@ -65,8 +85,35 @@ 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;
|
let res = event.data;
|
||||||
|
|
||||||
if (res.type == "evaluate_words_progress") {
|
if (res.type == "evaluate_words_progress") {
|
||||||
@@ -79,6 +126,8 @@ solver_worker.onmessage = (event: MessageEvent<SolverResponse>) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Rcv msg: ", res.type + " " + res.id);
|
||||||
|
|
||||||
const pendingRequest = pending.get(res.id);
|
const pendingRequest = pending.get(res.id);
|
||||||
|
|
||||||
if (!pendingRequest) {
|
if (!pendingRequest) {
|
||||||
@@ -95,4 +144,5 @@ solver_worker.onmessage = (event: MessageEvent<SolverResponse>) => {
|
|||||||
} else {
|
} else {
|
||||||
pendingRequest.reject("No result");
|
pendingRequest.reject("No result");
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ export type SolverRequest =
|
|||||||
type: "solution_space",
|
type: "solution_space",
|
||||||
id: number,
|
id: number,
|
||||||
input: null,
|
input: null,
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "reload_wordlist",
|
||||||
|
id: number,
|
||||||
|
input: ReloadWordlist
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SolverResponse =
|
export type SolverResponse =
|
||||||
@@ -33,6 +38,7 @@ export type SolverResponse =
|
|||||||
| {
|
| {
|
||||||
type: "evaluate_words_progress",
|
type: "evaluate_words_progress",
|
||||||
id: number,
|
id: number,
|
||||||
|
error: null,
|
||||||
result: EvaluateWordsProgress
|
result: EvaluateWordsProgress
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@@ -40,6 +46,12 @@ export type SolverResponse =
|
|||||||
id: number,
|
id: number,
|
||||||
error: string | null,
|
error: string | null,
|
||||||
result: SolutionSpaceResult | null
|
result: SolutionSpaceResult | null
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "reload_wordlist",
|
||||||
|
id: number,
|
||||||
|
error: string | null
|
||||||
|
result: boolean | null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Guess = {
|
export type Guess = {
|
||||||
@@ -56,6 +68,9 @@ export type EvaluateWordsProgress = {
|
|||||||
i: number,
|
i: number,
|
||||||
n: number
|
n: number
|
||||||
};
|
};
|
||||||
|
export type ReloadWordlist = {
|
||||||
|
use_wordle_ansers: boolean
|
||||||
|
};
|
||||||
export type WordStats = {
|
export type WordStats = {
|
||||||
word: string,
|
word: string,
|
||||||
solution_probability: number,
|
solution_probability: number,
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { Solver, } from "wordle-solver";
|
import { Solver, } from "wordle-solver";
|
||||||
import type { SolverRequest, SolverResponse, WordStats } from "./types";
|
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>) => {
|
self.onmessage = (event: MessageEvent<SolverRequest>) => {
|
||||||
const request = event.data;
|
const request = event.data;
|
||||||
@@ -40,6 +44,7 @@ self.onmessage = (event: MessageEvent<SolverRequest>) => {
|
|||||||
let p: SolverResponse = {
|
let p: SolverResponse = {
|
||||||
type: "evaluate_words_progress",
|
type: "evaluate_words_progress",
|
||||||
id: request.id,
|
id: request.id,
|
||||||
|
error: null,
|
||||||
result: { i, n }
|
result: { i, n }
|
||||||
};
|
};
|
||||||
self.postMessage(JSON.parse(JSON.stringify(p)));
|
self.postMessage(JSON.parse(JSON.stringify(p)));
|
||||||
@@ -77,10 +82,19 @@ self.onmessage = (event: MessageEvent<SolverRequest>) => {
|
|||||||
type: "solution_space",
|
type: "solution_space",
|
||||||
id: request.id,
|
id: request.id,
|
||||||
error: null,
|
error: null,
|
||||||
result: {
|
result: { size: solver.solution_space(), uncertainty: solver.solution_space_uncertainty() }
|
||||||
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)));
|
self.postMessage(JSON.parse(JSON.stringify(response)));
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user