Enhance exercise generation for family conversations and feelings & affection

- Updated multiple choice exercises to include randomized wrong options for improved engagement and challenge.
- Added new exercise types for reading aloud and speaking from memory, enhancing interactive learning experiences.
- Improved gap fill exercises with clearer instructions and multiple variants for better user understanding.
- Enhanced the vocabulary service to support new exercise types, ensuring robust answer checking and feedback mechanisms.
- Updated localization files to include new instructions and messages related to the new exercise types.
This commit is contained in:
Torsten Schulz (local)
2026-01-20 14:30:19 +01:00
parent e5d4a5f95f
commit 8d32d704b5
8 changed files with 612 additions and 105 deletions

View File

@@ -330,38 +330,72 @@ function createFamilyConversationExercises(nativeLanguageName) {
let exerciseNum = 1;
// Multiple Choice: Übersetze Bisaya-Satz in Muttersprache
// Multiple Choice: Übersetze Bisaya-Satz in Muttersprache (alle Gespräche)
conversations.forEach((conv, idx) => {
if (idx < 4) { // Erste 4 als Multiple Choice
// Erstelle für jedes Gespräch eine Multiple Choice Übung
const wrongOptions = conversations
.filter((c, i) => i !== idx)
.sort(() => Math.random() - 0.5)
.slice(0, 3)
.map(c => c.native);
const options = [conv.native, ...wrongOptions].sort(() => Math.random() - 0.5);
const correctIndex = options.indexOf(conv.native);
exercises.push({
exerciseTypeId: 2, // multiple_choice
exerciseNumber: exerciseNum++,
title: `Familien-Gespräch ${idx + 1} - Übersetzung`,
instruction: 'Übersetze den Bisaya-Satz ins ' + nativeLanguageName,
questionData: JSON.stringify({
type: 'multiple_choice',
question: `Wie sagt man "${conv.bisaya}" auf ${nativeLanguageName}?`,
options: options
}),
answerData: JSON.stringify({
type: 'multiple_choice',
correctAnswer: correctIndex
}),
explanation: conv.explanation
});
});
// Multiple Choice: Rückwärts-Übersetzung (Was bedeutet dieser Satz?)
conversations.forEach((conv, idx) => {
if (idx < 6) { // Erste 6 als Rückwärts-Übersetzung
const wrongOptions = conversations
.filter((c, i) => i !== idx)
.sort(() => Math.random() - 0.5)
.slice(0, 3)
.map(c => c.native);
const options = [conv.native, ...wrongOptions].sort(() => Math.random() - 0.5);
const correctIndex = options.indexOf(conv.native);
exercises.push({
exerciseTypeId: 2, // multiple_choice
exerciseNumber: exerciseNum++,
title: `Familien-Gespräch ${idx + 1} - Übersetzung`,
instruction: 'Übersetze den Bisaya-Satz ins ' + nativeLanguageName,
title: `Familien-Gespräch ${idx + 1} - Was bedeutet dieser Satz?`,
instruction: 'Was bedeutet dieser Bisaya-Satz?',
questionData: JSON.stringify({
type: 'multiple_choice',
question: `Wie sagt man "${conv.bisaya}" auf ${nativeLanguageName}?`,
options: [
conv.native,
conversations[(idx + 1) % conversations.length].native,
conversations[(idx + 2) % conversations.length].native,
conversations[(idx + 3) % conversations.length].native
]
question: `Was bedeutet "${conv.bisaya}"?`,
options: options
}),
answerData: JSON.stringify({
type: 'multiple_choice',
correctAnswer: 0
correctAnswer: correctIndex
}),
explanation: conv.explanation
});
}
});
// Gap Fill: Vervollständige Familiengespräche
// Gap Fill: Vervollständige Familiengespräche (mehrere Varianten)
exercises.push({
exerciseTypeId: 1, // gap_fill
exerciseNumber: exerciseNum++,
title: 'Familien-Gespräch vervollständigen',
title: 'Familien-Gespräch 1 - Vervollständigen',
instruction: 'Vervollständige das Gespräch mit den richtigen Bisaya-Wörtern.',
questionData: JSON.stringify({
type: 'gap_fill',
@@ -375,44 +409,40 @@ function createFamilyConversationExercises(nativeLanguageName) {
explanation: '"Nanay" ist "Mama" und "Maayo ko" bedeutet "Mir geht es gut"'
});
// Transformation: Übersetze Muttersprache-Satz nach Bisaya
exercises.push({
exerciseTypeId: 3, // transformation
exerciseTypeId: 1, // gap_fill
exerciseNumber: exerciseNum++,
title: 'Familien-Gespräch - Übersetzung nach Bisaya',
instruction: 'Übersetze den Satz ins Bisaya.',
title: 'Familien-Gespräch 2 - Vervollständigen',
instruction: 'Vervollständige das Gespräch mit den richtigen Bisaya-Wörtern.',
questionData: JSON.stringify({
type: 'transformation',
text: conversations[0].native
type: 'gap_fill',
text: 'Person A: {gap} si Tatay? (Wo ist)\nPerson B: {gap} siya sa balay. (Er ist)',
gaps: 2
}),
answerData: JSON.stringify({
type: 'transformation',
correctAnswer: conversations[0].bisaya
type: 'gap_fill',
answers: ['Asa', 'Naa']
}),
explanation: `"${conversations[0].bisaya}" bedeutet "${conversations[0].native}" auf Bisaya. ${conversations[0].explanation}`
explanation: '"Asa" bedeutet "wo" und "Naa" bedeutet "ist/sein"'
});
// Weitere Multiple Choice: Rückwärts-Übersetzung
exercises.push({
exerciseTypeId: 2, // multiple_choice
exerciseNumber: exerciseNum++,
title: 'Familien-Gespräch - Was bedeutet dieser Satz?',
instruction: 'Was bedeutet dieser Bisaya-Satz?',
questionData: JSON.stringify({
type: 'multiple_choice',
question: `Was bedeutet "${conversations[2].bisaya}"?`,
options: [
conversations[2].native,
conversations[3].native,
conversations[4].native,
conversations[5].native
]
}),
answerData: JSON.stringify({
type: 'multiple_choice',
correctAnswer: 0
}),
explanation: conversations[2].explanation
// Transformation: Übersetze Muttersprache-Satz nach Bisaya (mehrere Varianten)
conversations.slice(0, 4).forEach((conv, idx) => {
exercises.push({
exerciseTypeId: 3, // transformation
exerciseNumber: exerciseNum++,
title: `Familien-Gespräch ${idx + 1} - Übersetzung nach Bisaya`,
instruction: 'Übersetze den Satz ins Bisaya.',
questionData: JSON.stringify({
type: 'transformation',
text: conv.native
}),
answerData: JSON.stringify({
type: 'transformation',
correctAnswer: conv.bisaya
}),
explanation: `"${conv.bisaya}" bedeutet "${conv.native}" auf Bisaya. ${conv.explanation}`
});
});
return exercises;

View File

@@ -330,38 +330,72 @@ function createFeelingsAffectionExercises(nativeLanguageName) {
let exerciseNum = 1;
// Multiple Choice: Übersetze Bisaya-Satz in Muttersprache
// Multiple Choice: Übersetze Bisaya-Satz in Muttersprache (alle Gespräche)
conversations.forEach((conv, idx) => {
if (idx < 4) { // Erste 4 als Multiple Choice
// Erstelle für jedes Gespräch eine Multiple Choice Übung
const wrongOptions = conversations
.filter((c, i) => i !== idx)
.sort(() => Math.random() - 0.5)
.slice(0, 3)
.map(c => c.native);
const options = [conv.native, ...wrongOptions].sort(() => Math.random() - 0.5);
const correctIndex = options.indexOf(conv.native);
exercises.push({
exerciseTypeId: 2, // multiple_choice
exerciseNumber: exerciseNum++,
title: `Gefühle & Zuneigung ${idx + 1} - Übersetzung`,
instruction: 'Übersetze den Bisaya-Satz ins ' + nativeLanguageName,
questionData: JSON.stringify({
type: 'multiple_choice',
question: `Wie sagt man "${conv.bisaya}" auf ${nativeLanguageName}?`,
options: options
}),
answerData: JSON.stringify({
type: 'multiple_choice',
correctAnswer: correctIndex
}),
explanation: conv.explanation
});
});
// Multiple Choice: Rückwärts-Übersetzung (Was bedeutet dieser Satz?)
conversations.forEach((conv, idx) => {
if (idx < 6) { // Erste 6 als Rückwärts-Übersetzung
const wrongOptions = conversations
.filter((c, i) => i !== idx)
.sort(() => Math.random() - 0.5)
.slice(0, 3)
.map(c => c.native);
const options = [conv.native, ...wrongOptions].sort(() => Math.random() - 0.5);
const correctIndex = options.indexOf(conv.native);
exercises.push({
exerciseTypeId: 2, // multiple_choice
exerciseNumber: exerciseNum++,
title: `Gefühle & Zuneigung ${idx + 1} - Übersetzung`,
instruction: 'Übersetze den Bisaya-Satz ins ' + nativeLanguageName,
title: `Gefühle & Zuneigung ${idx + 1} - Was bedeutet dieser Satz?`,
instruction: 'Was bedeutet dieser Bisaya-Satz?',
questionData: JSON.stringify({
type: 'multiple_choice',
question: `Wie sagt man "${conv.bisaya}" auf ${nativeLanguageName}?`,
options: [
conv.native,
conversations[(idx + 1) % conversations.length].native,
conversations[(idx + 2) % conversations.length].native,
conversations[(idx + 3) % conversations.length].native
]
question: `Was bedeutet "${conv.bisaya}"?`,
options: options
}),
answerData: JSON.stringify({
type: 'multiple_choice',
correctAnswer: 0
correctAnswer: correctIndex
}),
explanation: conv.explanation
});
}
});
// Gap Fill: Vervollständige Gefühlsausdrücke
// Gap Fill: Vervollständige Gefühlsausdrücke (mehrere Varianten)
exercises.push({
exerciseTypeId: 1, // gap_fill
exerciseNumber: exerciseNum++,
title: 'Gefühle & Zuneigung vervollständigen',
title: 'Gefühle & Zuneigung 1 - Vervollständigen',
instruction: 'Vervollständige den Satz mit den richtigen Bisaya-Wörtern.',
questionData: JSON.stringify({
type: 'gap_fill',
@@ -375,44 +409,40 @@ function createFeelingsAffectionExercises(nativeLanguageName) {
explanation: '"Gihigugma" bedeutet "lieben" und wird wiederholt, um "auch" auszudrücken'
});
// Transformation: Übersetze Muttersprache-Satz nach Bisaya
exercises.push({
exerciseTypeId: 3, // transformation
exerciseTypeId: 1, // gap_fill
exerciseNumber: exerciseNum++,
title: 'Gefühle & Zuneigung - Übersetzung nach Bisaya',
instruction: 'Übersetze den Satz ins Bisaya.',
title: 'Gefühle & Zuneigung 2 - Vervollständigen',
instruction: 'Vervollständige den Satz mit den richtigen Bisaya-Wörtern.',
questionData: JSON.stringify({
type: 'transformation',
text: conversations[0].native
type: 'gap_fill',
text: 'Person A: {gap} ko nga nakita ka. (Ich bin glücklich)\nPerson B: {gap} ko pud. (Ich auch)',
gaps: 2
}),
answerData: JSON.stringify({
type: 'transformation',
correctAnswer: conversations[0].bisaya
type: 'gap_fill',
answers: ['Nalipay', 'Nalipay']
}),
explanation: `"${conversations[0].bisaya}" bedeutet "${conversations[0].native}" auf Bisaya. ${conversations[0].explanation}`
explanation: '"Nalipay" bedeutet "glücklich sein"'
});
// Weitere Multiple Choice: Rückwärts-Übersetzung
exercises.push({
exerciseTypeId: 2, // multiple_choice
exerciseNumber: exerciseNum++,
title: 'Gefühle & Zuneigung - Was bedeutet dieser Satz?',
instruction: 'Was bedeutet dieser Bisaya-Satz?',
questionData: JSON.stringify({
type: 'multiple_choice',
question: `Was bedeutet "${conversations[2].bisaya}"?`,
options: [
conversations[2].native,
conversations[3].native,
conversations[4].native,
conversations[5].native
]
}),
answerData: JSON.stringify({
type: 'multiple_choice',
correctAnswer: 0
}),
explanation: conversations[2].explanation
// Transformation: Übersetze Muttersprache-Satz nach Bisaya (mehrere Varianten)
conversations.slice(0, 4).forEach((conv, idx) => {
exercises.push({
exerciseTypeId: 3, // transformation
exerciseNumber: exerciseNum++,
title: `Gefühle & Zuneigung ${idx + 1} - Übersetzung nach Bisaya`,
instruction: 'Übersetze den Satz ins Bisaya.',
questionData: JSON.stringify({
type: 'transformation',
text: conv.native
}),
answerData: JSON.stringify({
type: 'transformation',
correctAnswer: conv.bisaya
}),
explanation: `"${conv.bisaya}" bedeutet "${conv.native}" auf Bisaya. ${conv.explanation}`
});
});
return exercises;