Update TTS providers and story markup

This commit is contained in:
2026-05-20 22:13:31 +02:00
parent b911c40d89
commit 8258ea2321
36 changed files with 1482 additions and 197 deletions
+58 -2
View File
@@ -35,6 +35,9 @@ class ChoiceDisplayModule extends BaseModule {
'render',
'clear',
'normalizeChoices',
'orderChoicesForPresentation',
'shuffleChoices',
'randomInt',
'assignLetters',
'selectChoice',
'getTagValue',
@@ -137,7 +140,7 @@ class ChoiceDisplayModule extends BaseModule {
}
normalizeChoices(choices) {
return this.assignLetters(choices.slice(0, 36).map((choice, order) => {
const normalized = choices.slice(0, 36).map((choice, order) => {
const tags = Array.isArray(choice.tags) ? choice.tags : [];
const category = choice.category || this.getTagValue(tags, 'action');
return {
@@ -145,11 +148,64 @@ class ChoiceDisplayModule extends BaseModule {
text: String(choice.text || ''),
tags,
category,
sourceOrder: order,
optional: this.hasTag(tags, 'optional'),
letter: '',
templateCell: this.getTemplateCell({ ...choice, tags, category })
};
}));
});
return this.assignLetters(this.orderChoicesForPresentation(normalized));
}
orderChoicesForPresentation(choices) {
const groupOrder = [];
const grouped = new Map();
const ungrouped = [];
choices.forEach((choice) => {
const group = String(choice.category || '').trim();
if (!group) {
ungrouped.push(choice);
return;
}
if (!grouped.has(group)) {
grouped.set(group, []);
groupOrder.push(group);
}
grouped.get(group).push(choice);
});
const ordered = [];
groupOrder.forEach((group) => {
ordered.push(...this.shuffleChoices(grouped.get(group) || []));
});
if (ungrouped.length > 0) {
ordered.push(...this.shuffleChoices(ungrouped));
}
return ordered;
}
shuffleChoices(choices) {
const shuffled = choices.slice();
for (let index = shuffled.length - 1; index > 0; index -= 1) {
const swapIndex = this.randomInt(index + 1);
[shuffled[index], shuffled[swapIndex]] = [shuffled[swapIndex], shuffled[index]];
}
return shuffled;
}
randomInt(exclusiveMax) {
const max = Math.max(1, Number(exclusiveMax) || 1);
if (window.crypto && typeof window.crypto.getRandomValues === 'function') {
const values = new Uint32Array(1);
window.crypto.getRandomValues(values);
return values[0] % max;
}
return Math.floor(Math.random() * max);
}
assignLetters(choices) {