Skip to content
Open
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
64 changes: 50 additions & 14 deletions frontend/src/ts/test/funbox/funbox-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,19 +146,58 @@ class PseudolangWordGenerator extends Wordset {
}

export class PolyglotWordset extends Wordset {
public wordsWithLanguage: Map<string, Language>;
public languageProperties: Map<Language, JSONData.LanguageProperties>;
readonly wordsMap: Map<Language, Wordset>;
readonly languageProperties: Map<Language, JSONData.LanguageProperties>;
private currLang: Language;
readonly langs: Language[];

constructor(
wordsWithLanguage: Map<string, Language>,
wordsMap: Map<Language, Wordset>,
languageProperties: Map<Language, JSONData.LanguageProperties>,
) {
// build and shuffle the word array
const wordArray = Array.from(wordsWithLanguage.keys());
Arrays.shuffle(wordArray);
super(wordArray);
this.wordsWithLanguage = wordsWithLanguage;
super([]);
this.languageProperties = languageProperties;
this.langs = Array.from(languageProperties.keys());
this.wordsMap = wordsMap;
this.resetIndexes();
this.length = Array.from(this.wordsMap.values()).reduce(
(sum, ws) => sum + ws.words.length,
0,
);
Comment on lines +158 to +166
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

PolyglotWordset now calls super([]) and never populates this.words. Code in words-generator relies on currentWordset.words (eg repeat-quote path + hasTab/hasNewline checks), so polyglot wordsets will report an empty list. Consider keeping words as an aggregate of all per-language words (or overriding/adding an accessor and updating consumers to use it).

Suggested change
super([]);
this.languageProperties = languageProperties;
this.langs = Array.from(languageProperties.keys());
this.wordsMap = wordsMap;
this.resetIndexes();
this.length = Array.from(this.wordsMap.values()).reduce(
(sum, ws) => sum + ws.words.length,
0,
);
const aggregatedWords = Array.from(wordsMap.values()).reduce<string[]>(
(all, ws) => all.concat(ws.words),
[],
);
super(aggregatedWords);
this.languageProperties = languageProperties;
this.langs = Array.from(languageProperties.keys());
this.wordsMap = wordsMap;
this.resetIndexes();
this.length = aggregatedWords.length;

Copilot uses AI. Check for mistakes.
this.currLang = this.langs[0] as Language;
}

get currentLanguage(): Language {
return this.currLang;
}

override resetIndexes(): void {
this.wordsMap.forEach((ws, _) => {
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

resetIndexes() uses this.wordsMap.forEach((ws, _) => ...) but the key param is unused. Drop the second arg to avoid unused-var lint noise.

Suggested change
this.wordsMap.forEach((ws, _) => {
this.wordsMap.forEach(ws => {

Copilot uses AI. Check for mistakes.
ws.resetIndexes();
});
}

private uniformLang(): Language {
const index = Math.floor(Math.random() * this.langs.length);
this.currLang = this.langs[index] as Language;
return this.currLang;
}

private getWordset(): Wordset {
const lang = this.uniformLang();
return this.wordsMap.get(lang) as Wordset;
}

override randomWord(mode: FunboxWordsFrequency): string {
return this.getWordset().randomWord(mode);
}

override shuffledWord(): string {
return this.getWordset().shuffledWord();
}

override nextWord(): string {
return this.getWordset().nextWord();
}
}

Expand Down Expand Up @@ -764,13 +803,10 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
]),
);

const wordsWithLanguage = new Map(
languages.flatMap((lang) =>
lang.words.map((word) => [word, lang.name]),
),
const wordsMap: Map<Language, Wordset> = new Map(
languages.map((lang) => [lang.name, new Wordset(lang.words)]),
);

return new PolyglotWordset(wordsWithLanguage, languageProperties);
return new PolyglotWordset(wordsMap, languageProperties);
},
},
};
Expand Down
21 changes: 8 additions & 13 deletions frontend/src/ts/test/words-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ async function applyBritishEnglishToWord(
function applyLazyModeToWord(word: string, language: LanguageObject): string {
// polyglot mode, use the word's actual language
if (currentWordset && currentWordset instanceof PolyglotWordset) {
const langName = currentWordset.wordsWithLanguage.get(word);
const langName = currentWordset.currentLanguage;
const langProps = langName
? currentWordset.languageProperties.get(langName)
: undefined;
Expand Down Expand Up @@ -508,9 +508,8 @@ async function getQuoteWordList(
// because it will be reversed again in the generateWords function
if (wordOrder === "reverse") {
return currentWordset.words.reverse();
} else {
return currentWordset.words;
}
return currentWordset.words;
}
const languageToGet = language.name.startsWith("swiss_german")
? "german"
Expand Down Expand Up @@ -655,17 +654,13 @@ export async function generateWords(

const funbox = findSingleActiveFunboxWithFunction("withWords");
if (funbox) {
const result = await funbox.functions.withWords(wordList);
currentWordset = await funbox.functions.withWords(wordList);
// PolyglotWordset if polyglot otherwise Wordset
if (result instanceof PolyglotWordset) {
const polyglotResult = result;
currentWordset = polyglotResult;
if (currentWordset instanceof PolyglotWordset) {
// set allLigatures if any language in languageProperties has ligatures true
ret.allLigatures = Array.from(
polyglotResult.languageProperties.values(),
currentWordset.languageProperties.values(),
).some((props) => !!props.ligatures);
} else {
currentWordset = result;
}
} else {
currentWordset = await withWords(wordList);
Expand Down Expand Up @@ -901,9 +896,9 @@ export async function getNextWord(

const usingFunboxWithGetWord = isFunboxActiveWithFunction("getWord");
const randomWordLanguage =
(currentWordset instanceof PolyglotWordset
? currentWordset.wordsWithLanguage.get(randomWord)
: Config.language) ?? Config.language; // Fall back to Config language if per-word language is unavailable
currentWordset instanceof PolyglotWordset
? currentWordset.currentLanguage
: Config.language; // Fall back to Config language if per-word language is unavailable

if (
Config.mode !== "custom" &&
Expand Down