import { useMemo, useState, type FormEvent } from "react"; import { GENERATOR_VARIANTS, type DifficultyAssessment, type GeneratedVariantPuzzle, type GenerationDifficultyTarget, type GeneratorVariant, type GenerateVariantOptions, } from "../solver"; const difficultyTargets: readonly GenerationDifficultyTarget[] = [ "beginner", "easy", "medium", "hard", "expert", ]; function techniqueLabel(value: string | undefined): string { return value === undefined ? "Direct placements" : value .split("-") .map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`) .join(" "); } export function GeneratorWorkspace({ busy, assessment, generation, onGenerate, onRate, }: { busy: boolean; assessment?: DifficultyAssessment; generation?: GeneratedVariantPuzzle; onGenerate: (options: GenerateVariantOptions) => void; onRate: () => void; }) { const [variant, setVariant] = useState("classic"); const definition = useMemo( () => GENERATOR_VARIANTS.find((item) => item.id === variant)!, [variant], ); const [size, setSize] = useState(9); const [targetDifficulty, setTargetDifficulty] = useState("medium"); const [symmetry, setSymmetry] = useState<"none" | "rotational">("rotational"); const [constraintCount, setConstraintCount] = useState(8); const [seed, setSeed] = useState(""); const usesMarkingCount = ![ "classic", "diagonal", "killer", "anti-knight", "anti-king", "non-consecutive", ].includes(variant); const submit = (event: FormEvent) => { event.preventDefault(); onGenerate({ variant, size, targetDifficulty, symmetry, ...(usesMarkingCount ? { constraintCount } : {}), seed: seed.trim() || `local-${Date.now().toString(36)}`, }); }; return (

Bounded local construction

Sudoku generator

Build a seedable, uniquely checked puzzle in the worker. The requested level guides clue removal; the finished puzzle receives an independent evidence-based rating.

{usesMarkingCount && ( )}

{definition.description}

Difficulty is an estimate from reproducible solver evidence, not a universal promise. Uniqueness is never claimed after a safety limit.

{assessment && (

Difficulty assessment

{assessment.label}

{assessment.uniqueness}
Score {assessment.score ?? "—"}/100 Givens {assessment.clueCount} Logical steps {assessment.logicalSteps} Hardest{" "} {techniqueLabel(assessment.hardestTechnique)} Search nodes {assessment.exactNodes} {generation && ( Markings {generation.generatedConstraintCount} )}

{assessment.summary}

{generation && (

Seed: {String(generation.seed)}

)}
)}
); }