Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions frontend/src/ts/test/funbox/funbox-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,15 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
else return "";
},
},
lefthand: {
async withWords(words?: string[]): Promise<Wordset> {
const LEFT_HAND_KEYS = new Set("qwertasdfgzxcvb");
const filtered = (words ?? []).filter((w) =>
[...w.toLowerCase()].every((ch) => LEFT_HAND_KEYS.has(ch)),
Comment on lines +569 to +571
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LEFT_HAND_KEYS is recreated on every withWords call. Consider hoisting the allowed-chars set/regex to module scope to avoid repeated allocations during word regeneration and keep this function simpler.

Copilot uses AI. Check for mistakes.
);
return new Wordset(filtered.length > 0 ? filtered : ["test"]);
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the filtered list is empty, this returns new Wordset(["test"]), which silently replaces the user’s language/custom word list with a single placeholder word. Better to surface this as an unsupported scenario (e.g. show a notice, disable the funbox, and/or throw a WordGenError to trigger regeneration) so users aren’t stuck typing "test" repeatedly.

Suggested change
return new Wordset(filtered.length > 0 ? filtered : ["test"]);
if (filtered.length === 0) {
throw new WordGenError(
"No left-hand-only words available for the current word list.",
);
}
return new Wordset(filtered);

Copilot uses AI. Check for mistakes.
},
Comment on lines +567 to +574
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No unit test covers the new lefthand.withWords filtering behavior (allowed letters + empty-result handling). Since the repo already has Vitest coverage for funbox wiring (frontend/__tests__/test/funbox.spec.ts), consider adding a small test that asserts filtering works and that the empty-match case behaves as intended.

Copilot uses AI. Check for mistakes.
},
pseudolang: {
async withWords(words?: string[]): Promise<Wordset> {
if (words !== undefined) return new PseudolangWordGenerator(words);
Expand Down
8 changes: 8 additions & 0 deletions packages/funbox/src/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,14 @@ const list: Record<FunboxName, FunboxMetadata> = {
frontendFunctions: ["getWord"],
name: "weakspot",
},
lefthand: {
description: "Only words typeable with the left hand.",
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funbox description says "Only words typeable with the left hand." but the implementation hardcodes QWERTY left-hand letters. This is user-facing text; either mention QWERTY explicitly here, or update the implementation to derive left-hand keys from the active layout (similar to the leftHand preset logic in frontend/src/ts/modals/word-filter.ts).

Suggested change
description: "Only words typeable with the left hand.",
description: "Only words typeable with the left hand on QWERTY.",

Copilot uses AI. Check for mistakes.
canGetPb: false,
difficultyLevel: 1,
properties: ["changesWordsFrequency"],
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lefthand is marked changesWordsFrequency, which makes it incompatible with zipf (and any other frequency-changer) via funbox compatibility checks. Since this funbox filters the word list via withWords rather than changing selection frequency, consider removing changesWordsFrequency so lefthand can still be combined with zipf/future frequency modes.

Suggested change
properties: ["changesWordsFrequency"],
properties: [],

Copilot uses AI. Check for mistakes.
frontendFunctions: ["withWords"],
name: "lefthand",
},
pseudolang: {
description: "Nonsense words that look like the current language.",
canGetPb: false,
Expand Down
1 change: 1 addition & 0 deletions packages/schemas/src/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ export const FunboxNameSchema = z.enum([
"asl",
"rot13",
"no_quit",
"lefthand",
]);
export type FunboxName = z.infer<typeof FunboxNameSchema>;

Expand Down
Loading