From 5f013dbdfe0a1d65b6f8ffe673a643d6d7e722f0 Mon Sep 17 00:00:00 2001 From: "Chris W. Fuller" Date: Wed, 21 Oct 2026 04:53:52 +0000 Subject: [PATCH] Add Wortbaukasten, Preposition+Case trainer, and Listening Dictation modules --- app.js | 807 +++++++++++++++++++++++++++++++++++++++++++++ data/hover_dict.js | 35 +- data/labs.js | 562 +++++++++++++++++++++++++++++++ index.html | 128 +++++-- styles.css | 137 ++++++++ 5 files changed, 1646 insertions(+), 23 deletions(-) create mode 100644 data/labs.js diff --git a/app.js b/app.js index 4f6cef7..70b1078 100644 --- a/app.js +++ b/app.js @@ -25,6 +25,26 @@ class WortKraftApp { this.spotlightWords = []; this.pendingTranslations = new Set(); + // 1) Wortbaukasten (Compound & Prefix Lab) state + this.builderSubmode = "prefixes"; // 'prefixes' | 'compounds' | 'quiz' + this.selectedVerbRoot = "nehmen"; + this.builderQuizIndex = 0; + this.builderQuizResult = null; + + // 2) Verben mit Präposition (Rektion & Da-/Wo-) state + this.prepSubmode = "drill"; // 'drill' | 'dawo' | 'reference' + this.prepIndex = 0; + this.prepResult = null; + this.daWoIndex = 0; + this.daWoResult = null; + + // 3) Hörtraining (Listening Dictation & Shadowing) state + this.listeningIndex = 0; + this.listeningShowHint = false; + this.listeningResult = null; + this.speechResult = null; + this.isRecordingMic = false; + this.loadState(); this.hoverTranslateEnabled = this.settings.hoverTranslateEnabled !== false; this.initScenarioStates(); @@ -477,6 +497,12 @@ class WortKraftApp { } else if (viewName === "trainer") { if (!this.currentCard) this.pickNextCard(); this.renderTrainerStage(); + } else if (viewName === "builder") { + this.renderBuilderStage(); + } else if (viewName === "prepositions") { + this.renderPrepositionsStage(); + } else if (viewName === "listening") { + this.renderListeningStage(); } else if (viewName === "reader") { this.renderReaderSidebar(); this.renderReaderMain(); @@ -1924,6 +1950,787 @@ class WortKraftApp { .replace(/\n/g, " "); } + // === 1) WORTBAUKASTEN (COMPOUND WORD & PREFIX LAB) === + setBuilderSubmode(submode) { + this.builderSubmode = submode; + this.builderQuizResult = null; + ["prefixes", "compounds", "quiz"].forEach(m => { + const btn = document.getElementById(`builder-tab-${m}`); + if (btn) btn.classList.toggle("active", m === submode); + }); + this.renderBuilderStage(); + } + + selectVerbRoot(rootName) { + this.selectedVerbRoot = rootName; + this.renderBuilderStage(); + } + + saveLabItemToDeck(word, article, plural, english, exampleDe, exampleEn, note) { + const existing = this.vocab.find(v => v.word.toLowerCase() === word.toLowerCase()); + if (existing) { + existing.srs.dueDate = Date.now() - 1000; + this.saveState(); + this.showToast(`⚡ „${word}“ wurde im SRS-Trainer priorisiert!`); + return; + } + const newEntry = this.createVocabEntry({ + id: "lab_" + Date.now() + "_" + Math.floor(Math.random() * 1000), + word, + article: article || null, + plural: plural || null, + pos: article ? "noun" : "verb", + level: "A2/B1", + category: "Everyday & Bureaucracy", + english, + breakdown: note, + forms: plural, + exampleDe, + exampleEn: exampleEn || "", + clozeSentence: exampleDe.replace(new RegExp(word, "i"), "___"), + clozeAnswer: word, + usageTip: note + }); + this.vocab.unshift(newEntry); + this.saveState(); + this.showToast(`➕ „${word}“ zum SRS-Trainer hinzugefügt!`); + } + + getBuilderQuizItems() { + const data = window.WORD_BUILDER_DATA; + if (!data) return []; + const items = []; + data.verbRoots.forEach(r => { + r.derivatives.forEach(d => { + items.push({ + type: "prefix", + root: r.root, + word: d.word, + separable: d.separable, + english: d.english, + promptDe: d.quizCloze, + answer: d.quizAnswer, + explanation: `${d.word} (${d.forms}) — ${d.logic}` + }); + }); + }); + data.compounds.forEach(c => { + items.push({ + type: "compound", + compound: c.compound, + finalArticle: c.finalArticle, + english: c.english, + parts: c.parts, + explanation: c.ruleNote, + exampleDe: c.exampleDe + }); + }); + return items; + } + + checkBuilderQuizAnswer(userVal) { + const items = this.getBuilderQuizItems(); + const item = items[this.builderQuizIndex % items.length]; + if (!item) return; + + this.stats.totalChecks++; + if (item.type === "prefix") { + const isCorrect = this.normalizeGerman(userVal) === this.normalizeGerman(item.answer); + if (isCorrect) this.stats.correctChecks++; + this.builderQuizResult = { + isCorrect, + message: isCorrect + ? `✅ Richtig! „${item.answer}“ (${item.word} — ${item.separable ? "trennbar" : "untrennbar"}).` + : `❌ Fast! Gesucht war: „${item.answer}“ (${item.word}).` + }; + this.speak(item.promptDe.replace("___", item.answer)); + } else { + const isCorrect = userVal === item.finalArticle; + if (isCorrect) this.stats.correctChecks++; + this.builderQuizResult = { + isCorrect, + message: isCorrect + ? `✅ Perfekt! Das letzte Wort bestimmt den Artikel: ${item.finalArticle} ${item.compound}!` + : `❌ Nicht ganz: Das letzte Wort in „${item.compound}“ bestimmt den Artikel → ${item.finalArticle} ${item.compound}!` + }; + this.speak(`${item.finalArticle} ${item.compound}`); + } + this.saveState(); + this.renderBuilderStage(); + } + + nextBuilderQuiz() { + const items = this.getBuilderQuizItems(); + this.builderQuizIndex = (this.builderQuizIndex + 1) % items.length; + this.builderQuizResult = null; + this.renderBuilderStage(); + } + + renderBuilderStage() { + const container = document.getElementById("builder-stage-container"); + const data = window.WORD_BUILDER_DATA; + if (!container || !data) return; + + if (this.builderSubmode === "prefixes") { + const activeRoot = data.verbRoots.find(r => r.root === this.selectedVerbRoot) || data.verbRoots[0]; + const rootPills = data.verbRoots + .map( + r => ` + + ` + ) + .join(""); + + const cardsHtml = activeRoot.derivatives + .map( + d => ` +
+
+
+ + ${d.separable ? "✂️ Trennbar (mit -ge-)" : "🔒 Untrennbar (ohne -ge-)"} + +
+
+ + +
+
+
+ ${d.prefix}${activeRoot.root} → ${d.word} +
+
${d.forms}
+
${d.english}
+
💡 Logik: ${d.logic}
+
+ „${this.tokenizeSentenceForHover(d.exampleDe)}“ +
${d.exampleEn}
+
+
+ ` + ) + .join(""); + + container.innerHTML = ` +
+
+
+

🔀 Verb-Stämme & Präfix-Labor

+

+ Ein einziger deutscher Verbstamm bildet durch Vorsilben (Präfixe) dutzende neue Wörter. + Trennbare Präfixe (an-, ab-, auf-, aus-, mit-, vor-, teil-) sind betont und bekommen im Perfekt -ge- in der Mitte. + Untrennbare Präfixe (be-, ver-, ent-, er-, über-, unter-) bekommen kein -ge-! +

+
+
+
+ ${rootPills} +
+
+ Grundverb: ${activeRoot.root} — ${activeRoot.baseMeaning} +
+
+ ${cardsHtml} +
+
+ `; + } else if (this.builderSubmode === "compounds") { + const compoundsHtml = data.compounds + .map(c => { + const blocksHtml = c.parts + .map((part, idx) => { + const isLast = idx === c.parts.length - 1; + return ` + ${idx > 0 ? `
+
` : ""} +
+
+ ${part.article ? this.getGenderBadgeHtml(part.article) : ""} + ${part.word} +
+ ${part.meaning} +
+ `; + }) + .join(""); + + return ` +
+
+
+ ${this.getGenderBadgeHtml(c.finalArticle)} + ${this.tokenizeSentenceForHover(c.compound)} + (${c.plural}) + — ${c.english} +
+
+ + +
+
+
+ ${blocksHtml} +
+
+ 🎯 Artikel-Regel: ${c.ruleNote} +
+
+ „${this.tokenizeSentenceForHover(c.exampleDe)}“ +
+
+ `; + }) + .join(""); + + container.innerHTML = ` +
+

🧱 Komposita-Knacker: Keine Angst vor langen deutschen Wörtern!

+

+ Goldene Regel: Egal wie lang ein zusammengesetztes Nomen ist — das allerletzte Baustein-Wort (gelb umrandet) bestimmt immer 100% den Artikel (der/die/das)! +

+
+ ${compoundsHtml} + `; + } else { + // Quiz submode + const items = this.getBuilderQuizItems(); + const item = items[this.builderQuizIndex % items.length]; + + let quizBody = ""; + if (item.type === "prefix") { + quizBody = ` +
🔀 Präfix-Verb im Kontext • Stamm: „${item.root}“
+
${item.english}
+
+
${this.tokenizeSentenceForHover(item.promptDe)}
+
+
+
+ + + +
+ ${this.renderUmlautBar("builder-quiz-input")} +
+ `; + } else { + const partsLine = item.parts.map(p => `${p.article ? p.article + " " : ""}${p.word}`).join(" + "); + quizBody = ` +
🧱 Komposita-Artikel-Challenge • Welcher Artikel gewinnt?
+
___ ${item.compound}
+
+ Bausteine: ${partsLine} (${item.english}) +
+
+ + + +
+ `; + } + + container.innerHTML = ` +
+
+ Wortbaukasten-Quiz • Frage ${(this.builderQuizIndex % items.length) + 1} / ${items.length} +
+ ${quizBody} + ${ + this.builderQuizResult + ? ` + + ` + : "" + } +
+ `; + } + } + + // === 2) VERBEN MIT PRÄPOSITION & KASUS (REKTION & DA-/WO-) === + setPrepSubmode(submode) { + this.prepSubmode = submode; + this.prepResult = null; + this.daWoResult = null; + ["drill", "dawo", "reference"].forEach(m => { + const btn = document.getElementById(`prep-tab-${m}`); + if (btn) btn.classList.toggle("active", m === submode); + }); + this.renderPrepositionsStage(); + } + + checkPrepDrillChoice(chosenOption) { + const drills = window.PREPOSITION_DRILLS || []; + const d = drills[this.prepIndex % drills.length]; + if (!d) return; + + this.stats.totalChecks++; + const cleanChosen = chosenOption.split(" (")[0].trim().toLowerCase(); + const isCorrect = + cleanChosen === d.correctCombo.toLowerCase() || + (d.acceptedAnswers || []).some(a => a.toLowerCase() === cleanChosen); + + if (isCorrect) this.stats.correctChecks++; + + const fullSentence = `${d.sentenceBefore} ${d.correctCombo} ${d.sentenceAfter}`; + this.prepResult = { + isCorrect, + fullSentence, + message: isCorrect + ? `✅ Perfekt! „${d.verb} + ${d.preposition} + ${d.grammaticalCase}“ → „${d.correctCombo}“.` + : `❌ Fast! Du hast „${chosenOption}“ gewählt, aber richtig ist: „${d.correctCombo}“ (${d.verb} + ${d.preposition} + ${d.grammaticalCase}).` + }; + this.saveState(); + this.speak(fullSentence); + this.renderPrepositionsStage(); + } + + nextPrepDrill() { + const drills = window.PREPOSITION_DRILLS || []; + this.prepIndex = (this.prepIndex + 1) % drills.length; + this.prepResult = null; + this.renderPrepositionsStage(); + } + + checkDaWoAnswer(chosenWord) { + const drills = window.PREPOSITION_DRILLS || []; + const d = drills[this.daWoIndex % drills.length]; + if (!d) return; + + this.stats.totalChecks++; + const isCorrect = chosenWord.toLowerCase() === d.daForm.toLowerCase(); + if (isCorrect) this.stats.correctChecks++; + + this.daWoResult = { + isCorrect, + message: isCorrect + ? `✅ Genau richtig! da(r) + ${d.preposition} = „${d.daForm}“ (Fragewort: „${d.woForm}“).` + : `❌ Nicht ganz: Zu „${d.verb} + ${d.preposition}“ gehört „${d.daForm}“ (und als Frage: „${d.woForm}“).` + }; + this.saveState(); + this.speak(d.daExampleDe); + this.renderPrepositionsStage(); + } + + nextDaWoDrill() { + const drills = window.PREPOSITION_DRILLS || []; + this.daWoIndex = (this.daWoIndex + 1) % drills.length; + this.daWoResult = null; + this.renderPrepositionsStage(); + } + + renderPrepositionsStage() { + const container = document.getElementById("prepositions-stage-container"); + const drills = window.PREPOSITION_DRILLS || []; + if (!container || drills.length === 0) return; + + if (this.prepSubmode === "drill") { + const d = drills[this.prepIndex % drills.length]; + const optionsHtml = d.options + .map( + opt => ` + + ` + ) + .join(""); + + container.innerHTML = ` +
+
+ Präposition & Kasus • ${(this.prepIndex % drills.length) + 1} / ${drills.length} + + Verb: ${d.verb} (${d.english}) + +
+ +
🎯 Wähle die richtige Präposition + Artikel im richtigen Fall (Akkusativ / Dativ)
+
+
+ ${this.tokenizeSentenceForHover(d.sentenceBefore)} + [ ___ ] + ${this.tokenizeSentenceForHover(d.sentenceAfter)} +
+
+ Nomen-Hinweis: ${d.nounHint} +
+
+ +
+ ${optionsHtml} +
+ + ${ + this.prepResult + ? ` + + ` + : "" + } +
+ `; + } else if (this.prepSubmode === "dawo") { + const d = drills[this.daWoIndex % drills.length]; + const daChoices = ["darauf", "darüber", "darum", "daran", "davon", "dafür"]; + const clozeDaSentence = d.daExampleDe.replace(new RegExp(d.daForm, "i"), "___"); + + container.innerHTML = ` +
+
+ Da- & Wo-Baukasten • ${(this.daWoIndex % drills.length) + 1} / ${drills.length} + ${d.verb} + ${d.preposition} (${d.grammaticalCase}) +
+ +
🔗 Wie ersetzen Deutsche einen ganzen Satzteil durch ein „da-Wort“?
+

+ Regel: da + Präposition (bei Vokal a/o/u/ü mit -r- dazwischen: da + r + auf = darauf). +

+ +
+
${this.tokenizeSentenceForHover(clozeDaSentence)}
+
Gesuchtes Verb: ${d.verb} (${d.english})
+
+ +
+ ${daChoices + .map( + ch => ` + + ` + ) + .join("")} +
+ + ${ + this.daWoResult + ? ` + + ` + : "" + } +
+ `; + } else { + // Reference table + container.innerHTML = ` +
+

📋 Die wichtigsten A2/B1 Verben mit fester Präposition

+

+ Lerne jedes Verb immer zusammen mit seiner Präposition und dem Fall (Akkusativ oder Dativ). +

+
+ ${drills + .map( + d => ` +
+
+
+ ${d.verb} ${d.preposition} + + ${d.grammaticalCase} +
+
${d.english}
+
+ Da-/Wo-Form: ${d.daForm} • ${d.woForm}? +
+
+ „${this.tokenizeSentenceForHover(`${d.sentenceBefore} ${d.correctCombo} ${d.sentenceAfter}`)}“ +
+
+
+ + +
+
+ ` + ) + .join("")} +
+
+ `; + } + } + + // === 3) HÖRTRAINING & AUSSPRACHE (LISTENING DICTATION & SHADOWING) === + computeWordDiffHtml(expectedSentence, userSentence) { + const cleanWord = w => w.toLowerCase().replace(/[.,!?„“"']/g, ""); + const expectedWords = expectedSentence.split(/\s+/).filter(Boolean); + const userWords = (userSentence || "").split(/\s+/).filter(Boolean).map(cleanWord); + + let matchedCount = 0; + const diffHtml = expectedWords + .map(expW => { + const normExp = cleanWord(expW); + const foundIdx = userWords.indexOf(normExp); + if (foundIdx !== -1) { + userWords.splice(foundIdx, 1); + matchedCount++; + return `${expW}`; + } + return `${expW}`; + }) + .join(" "); + + const scorePct = Math.round((matchedCount / expectedWords.length) * 100); + return { diffHtml, scorePct, matchedCount, total: expectedWords.length }; + } + + checkListeningDictation(e) { + e.preventDefault(); + const input = document.getElementById("listening-dictation-input"); + if (!input) return; + const userText = input.value.trim(); + if (!userText) return; + + const list = window.LISTENING_EXERCISES || []; + const ex = list[this.listeningIndex % list.length]; + if (!ex) return; + + const { diffHtml, scorePct, matchedCount, total } = this.computeWordDiffHtml(ex.de, userText); + this.stats.totalChecks++; + this.stats.sentencesWritten++; + if (scorePct >= 80) this.stats.correctChecks++; + + this.listeningResult = { + userText, + diffHtml, + scorePct, + matchedCount, + total + }; + this.saveState(); + this.renderListeningStage(); + } + + toggleListeningHint() { + this.listeningShowHint = !this.listeningShowHint; + this.renderListeningStage(); + } + + nextListeningExercise() { + const list = window.LISTENING_EXERCISES || []; + this.listeningIndex = (this.listeningIndex + 1) % list.length; + this.listeningShowHint = false; + this.listeningResult = null; + this.speechResult = null; + this.renderListeningStage(); + const nextEx = list[this.listeningIndex % list.length]; + if (nextEx) this.speak(nextEx.de, 0.96); + } + + startMicrophonePronunciationCheck() { + const SpeechRec = window.SpeechRecognition || window.webkitSpeechRecognition; + if (!SpeechRec) { + this.showToast("Dein Browser unterstützt die Web Speech Mikrofon-Erkennung leider nicht (am besten Chrome oder Edge nutzen)."); + return; + } + + const list = window.LISTENING_EXERCISES || []; + const ex = list[this.listeningIndex % list.length]; + if (!ex) return; + + if (this.isRecordingMic && this.activeRecognition) { + this.activeRecognition.stop(); + return; + } + + const recognition = new SpeechRec(); + recognition.lang = "de-DE"; + recognition.interimResults = false; + recognition.maxAlternatives = 1; + + this.isRecordingMic = true; + this.activeRecognition = recognition; + this.renderListeningStage(); + + recognition.onresult = event => { + const transcript = event.results?.[0]?.[0]?.transcript || ""; + const { diffHtml, scorePct } = this.computeWordDiffHtml(ex.de, transcript); + this.speechResult = { + transcript, + diffHtml, + scorePct + }; + this.stats.sentencesWritten++; + this.saveState(); + }; + + recognition.onerror = event => { + this.showToast(`Mikrofon-Hinweis: ${event.error}`); + }; + + recognition.onend = () => { + this.isRecordingMic = false; + this.renderListeningStage(); + }; + + recognition.start(); + } + + renderListeningStage() { + const container = document.getElementById("listening-stage-container"); + const list = window.LISTENING_EXERCISES || []; + if (!container || list.length === 0) return; + + const ex = list[this.listeningIndex % list.length]; + const wordInitialsHint = ex.de + .split(" ") + .map(w => w[0] + "___") + .join(" "); + + container.innerHTML = ` +
+
+ 🎧 Hörtraining & Aussprache • ${(this.listeningIndex % list.length) + 1} / ${list.length} (${ex.level}) + ${ex.situation} +
+ +
+
+
+ Schritt 1: Höre den deutschen Satz (ohne Text!) +
+
+ Klicke auf Play und tippe unten genau, was du hörst. +
+
+
+ + +
+
+ +
+ + +
+ + ${ + this.listeningShowHint + ? ` +
+
🇬🇧 Bedeutung: „${ex.en}“
+
+ 🔤 Wort-Struktur (${ex.de.split(" ").length} Wörter): ${wordInitialsHint} +
+
+ ` + : "" + } + +
+
✍️ Diktat: Tippe den gehörten deutschen Satz
+
+ + +
+ ${this.renderUmlautBar("listening-dictation-input")} +
+ + ${ + this.listeningResult + ? ` + + ` + : "" + } + +
+
+
+
🎙️ Schritt 2: Shadowing & Aussprache-Check (Optional)
+
+ Sprich den Satz laut auf Deutsch nach — die Spracherkennung prüft deine Aussprache Wort für Wort! +
+
+ +
+ + ${ + this.speechResult + ? ` + + ` + : "" + } +
+
+ `; + } + renderAll() { this.updateDashboardCounters(); this.renderDailySpotlight(); diff --git a/data/hover_dict.js b/data/hover_dict.js index d30b532..bdd4e79 100644 --- a/data/hover_dict.js +++ b/data/hover_dict.js @@ -236,5 +236,38 @@ window.HOVER_DICT = { "exportieren": "to export", "lernstand": "learning progress", "zurücksetzen": "to reset", "verständnis": "understanding / comprehension (das Verständnis)", "klicke": "click (imperative)", "wähle": "choose / select (imperative)", "versuche": "try (imperative)", - "fahre": "move / hover / drive", "maus": "mouse (die Maus)", "beliebiges": "any", "stammform": "base form / lemma" + "fahre": "move / hover / drive", "maus": "mouse (die Maus)", "beliebiges": "any", "stammform": "base form / lemma", + + // Labs: Wortbaukasten, Hörtraining & Verben mit Präposition + "wortbaukasten": "Word Building Kit / Compound & Prefix Lab (der Wortbaukasten)", + "hörtraining": "Listening Training (das Hörtraining)", + "diktat": "Dictation (das Diktat)", + "rektion": "Verb Preposition & Case Governance (die Rektion)", + "annehmen": "to accept / assume", "angenommen": "accepted / assumed", "paket": "package / parcel (das Paket)", "jobangebot": "job offer (das Jobangebot)", + "abnehmen": "to lose weight / take off", "abgenommen": "lost weight / taken off", "kilo": "kilogram(s) (das Kilo)", "frühling": "spring (der Frühling)", + "nimmst": "take (nimmst ... teil = take part)", "teil": "part (der/das Teil)", "kollegen": "colleagues (die Kollegen)", "besprechung": "meeting (die Besprechung)", "cappuccino": "cappuccino (der Cappuccino)", + "unternehmen": "to undertake / do an activity", "unternommen": "undertaken / done", "langen": "long", "schönes": "something nice", "tolle": "great / awesome", "ausflüge": "day trips / excursions (die Ausflüge)", + "übernehmen": "to take over / cover (costs)", "übernommen": "taken over / covered", "übernehme": "take over / cover", "kompletten": "complete / entire", + "vorstellen": "to introduce / imagine", "neuer": "new", "nachbar": "neighbor (der Nachbar)", "zweiten": "second", "ganzes": "whole / entire", "leben": "to live", + "bestellen": "to order", "bestellt": "ordered", "gewählt": "chosen / selected", "winterstiefel": "winter boots (die Winterstiefel)", "internet": "internet (das Internet)", + "ausstellen": "to issue (a document/prescription)", "ausgestellt": "issued", + "feststellen": "to realize / notice / determine", "festgestellt": "realized / noticed", "portemonnaie": "wallet (das Portemonnaie)", "liegt": "lies / is located", "auspacken": "unpacking (das Auspacken)", "fehlt": "is missing", + "welches": "which", "vorgeschlagen": "suggested / proposed", "nachschlagen": "to look up (in a dictionary)", "unbekannte": "unknown", "mühsam": "tediously / painstakingly", + "ankommen": "to arrive", "baustelle": "construction site / roadworks (die Baustelle)", "bekommen": "to get / receive", "steuer": "tax (die Steuer)", "nachricht": "message (die Nachricht)", + "lust": "desire / feel like (Lust haben = to feel like)", "glas": "glass (das Glas)", "wein": "wine (der Wein)", + "krankenversicherungskarte": "health insurance card (die Krankenversicherungskarte)", "legen": "to lay / present (legen ... vor)", "empfang": "reception desk (der Empfang)", + "wohnungsbesichtigung": "apartment viewing (die Wohnungsbesichtigung)", "samstagmittag": "Saturday noon", "online": "online", "freien": "free / available", + "bewahr": "keep / save (bewahr ... auf)", "falls": "in case / if", "gerät": "device / appliance (das Gerät)", + "feierabendbier": "after-work beer (das Feierabendbier)", "biergarten": "beer garden (der Biergarten)", "kühles": "cool / cold", + "nebenkostenabrechnung": "annual utility bill statement (die Nebenkostenabrechnung)", "nichts": "nothing", "nachzahlen": "to pay extra / back-pay", + "anschlussverbindung": "connecting train / transit connection (die Anschlussverbindung)", "warten": "to wait", "warte": "wait", "fahrgäste": "passengers (die Fahrgäste)", + "anrufen": "to call (on the phone)", "supermarktkasse": "supermarket checkout (die Supermarktkasse)", "wochenendausflug": "weekend trip (der Wochenendausflug)", "planen": "to plan", "reklamation": "complaint / return (die Reklamation)", "kaufhaus": "department store (das Kaufhaus)", + "kümmern": "to take care of (sich kümmern um)", "abendessen": "dinner / supper (das Abendessen)", "darum": "about it / of it (da + um)", "worum": "about what (wo + um)", + "freuen": "to be glad / look forward to", "zukunft": "future (die Zukunft)", "meer": "sea / ocean (das Meer)", "darauf": "to it / for it (da + auf)", + "gegenwart": "present (die Gegenwart)", "vergangenheit": "past (die Vergangenheit)", "nette": "nice / kind", "gefreut": "been happy / looked forward", "geholfen": "helped", "darüber": "about it (da + über)", "worüber": "about what (wo + über)", + "workshop": "workshop (der Workshop)", "daran": "in it / of it / to it (da + an)", "woran": "in what / of what (wo + an)", + "abhängen": "to depend (on)", "davon": "on it / from it (da + von)", "wovon": "on what / from what (wo + von)", + "gewöhnen": "to get used to (sich gewöhnen an)", "gewöhnt": "accustomed / used to", "ruhigen": "quiet / peaceful", "sonntage": "Sundays (die Sonntage)", "anfang": "beginning (am Anfang = at the beginning)", "bürokratie": "bureaucracy (die Bürokratie)", + "umzug": "move / relocation (der Umzug)", "interessieren": "to be interested (in)", "interessiert": "interested", "interessierst": "are interested", "wofür": "in what / for what (wo + für)", "dafür": "in it / for it (da + für)", "besonders": "especially / particularly", "kultur": "culture (die Kultur)", + "erinnern": "to remember (sich erinnern an)", "erinnerst": "remember", "erinnere": "remember" }; diff --git a/data/labs.js b/data/labs.js new file mode 100644 index 0000000..35f3eed --- /dev/null +++ b/data/labs.js @@ -0,0 +1,562 @@ +// WortKraft Labs Data — 1) Wortbaukasten (Compounds & Prefixes), 2) Hörtraining (Dictation & Shadowing), 3) Verben mit Präposition (Rektion & Da-/Wo-) + +window.WORD_BUILDER_DATA = { + verbRoots: [ + { + root: "nehmen", + baseMeaning: "to take (nimmt • nahm • hat genommen)", + derivatives: [ + { + word: "annehmen", + prefix: "an-", + separable: true, + forms: "nimmt an • nahm an • hat angenommen", + english: "to accept (a package/offer) / to assume", + logic: "an (at/toward) + nehmen (take) = take toward oneself → accept", + exampleDe: "Kannst du heute Nachmittag bitte das Paket für mich annehmen?", + exampleEn: "Can you please accept the package for me this afternoon?", + quizCloze: "Er hat das Jobangebot in München sofort ___.", + quizAnswer: "angenommen" + }, + { + word: "abnehmen", + prefix: "ab-", + separable: true, + forms: "nimmt ab • nahm ab • hat abgenommen", + english: "to take off / to lose weight / to decrease", + logic: "ab (off/down) + nehmen (take) = take off weight or load", + exampleDe: "Seit ich jeden Tag mit dem Fahrrad fahre, habe ich drei Kilo abgenommen.", + exampleEn: "Since I started riding my bike every day, I've lost three kilos.", + quizCloze: "Im Frühling möchte ich ein paar Kilo ___.", + quizAnswer: "abnehmen" + }, + { + word: "teilnehmen", + prefix: "teil-", + separable: true, + forms: "nimmt teil • nahm teil • hat teilgenommen", + english: "to participate / take part (an + Dative)", + logic: "Teil (part) + nehmen (take) = literally 'to take part'", + exampleDe: "Nimmst du morgen Abend auch an unserem Sprach-Stammtisch teil?", + exampleEn: "Are you also taking part in our language meetup tomorrow evening?", + quizCloze: "Wie viele Kollegen ___ heute an der Besprechung ___?", + quizAnswer: "nehmen teil" + }, + { + word: "mitnehmen", + prefix: "mit-", + separable: true, + forms: "nimmt mit • nahm mit • hat mitgenommen", + english: "to take along / to get food to-go ('zum Mitnehmen')", + logic: "mit (with) + nehmen (take) = take along with you", + exampleDe: "Einen großen Cappuccino zum Mitnehmen, bitte!", + exampleEn: "A large cappuccino to go, please!", + quizCloze: "Möchten Sie den Kaffee hier trinken oder zum ___?", + quizAnswer: "Mitnehmen" + }, + { + word: "unternehmen", + prefix: "unter-", + separable: false, + forms: "unternimmt • unternahm • hat unternommen (NO -ge-!)", + english: "to undertake / to do an activity together", + logic: "Inseparable prefix unter- (stressed on -nehmen): to venture into doing something", + exampleDe: "Wollen wir am langen Wochenende etwas Schönes zusammen unternehmen?", + exampleEn: "Shall we do something nice together over the long weekend?", + quizCloze: "Wir haben im Urlaub jeden Tag tolle Ausflüge ___.", + quizAnswer: "unternommen" + }, + { + word: "übernehmen", + prefix: "über-", + separable: false, + forms: "übernimmt • übernahm • hat übernommen (NO -ge-!)", + english: "to take over (a task, shift, or cost)", + logic: "Inseparable prefix über-: take over responsibility or payment", + exampleDe: "Die Krankenkasse hat die kompletten Kosten für die Untersuchung übernommen.", + exampleEn: "The health insurance provider covered the entire cost of the examination.", + quizCloze: "Keine Sorge, heute Abend ___ ich die Rechnung!", + quizAnswer: "übernehme" + } + ] + }, + { + root: "stellen", + baseMeaning: "to place / put upright / set (stellt • stellte • hat gestellt)", + derivatives: [ + { + word: "vorstellen", + prefix: "vor-", + separable: true, + forms: "stellt vor • stellte vor • hat vorgestellt", + english: "to introduce (sich + Acc) / to imagine (sich + Dat)", + logic: "vor (in front of) + stellen (place) = place before someone's eyes", + exampleDe: "Darf ich mich kurz vorstellen? Ich bin dein neuer Nachbar aus dem zweiten Stock.", + exampleEn: "May I introduce myself briefly? I'm your new neighbor from the second floor.", + quizCloze: "Kannst du dir ___, ein ganzes Jahr in Berlin zu leben?", + quizAnswer: "vorstellen" + }, + { + word: "bestellen", + prefix: "be-", + separable: false, + forms: "bestellt • bestellte • hat bestellt (NO -ge-!)", + english: "to order (food in a restaurant or items online)", + logic: "Inseparable be- + stellen: arrange for delivery/service", + exampleDe: "Haben Sie schon gewählt, oder möchten Sie erst Getränke bestellen?", + exampleEn: "Have you already chosen, or would you like to order drinks first?", + quizCloze: "Ich habe die neuen Winterstiefel gestern im Internet ___.", + quizAnswer: "bestellt" + }, + { + word: "ausstellen", + prefix: "aus-", + separable: true, + forms: "stellt aus • stellte aus • hat ausgestellt", + english: "to issue (a document/certificate/prescription) / to exhibit", + logic: "aus (out) + stellen = put out officially", + exampleDe: "Die Ärztin hat mir sofort ein Rezept und eine Krankschreibung ausgestellt.", + exampleEn: "The doctor immediately issued me a prescription and a sick note.", + quizCloze: "Das Bürgeramt hat meinen neuen Reisepass in drei Wochen ___.", + quizAnswer: "ausgestellt" + }, + { + word: "feststellen", + prefix: "fest-", + separable: true, + forms: "stellt fest • stellte fest • hat festgestellt", + english: "to realize / notice / determine", + logic: "fest (firm/fixed) + stellen = establish as a fact", + exampleDe: "An der Kasse habe ich plötzlich festgestellt, dass mein Portemonnaie zu Hause liegt.", + exampleEn: "At the checkout I suddenly realized that my wallet is at home.", + quizCloze: "Beim Auspacken musste ich leider ___, dass ein Teil fehlt.", + quizAnswer: "feststellen" + } + ] + }, + { + root: "schlagen", + baseMeaning: "to hit / beat / strike (schlägt • schlug • hat geschlagen)", + derivatives: [ + { + word: "vorschlagen", + prefix: "vor-", + separable: true, + forms: "schlägt vor • schlug vor • hat vorgeschlagen", + english: "to suggest / propose", + logic: "vor (forward) + schlagen = put a proposal forward", + exampleDe: "Ich schlage vor, dass wir uns direkt vor dem Rathaus treffen.", + exampleEn: "I suggest that we meet right in front of the town hall.", + quizCloze: "Welches Restaurant hast du für heute Abend ___?", + quizAnswer: "vorgeschlagen" + }, + { + word: "nachschlagen", + prefix: "nach-", + separable: true, + forms: "schlägt nach • schlug nach • hat nachgeschlagen", + english: "to look up (a word in a dictionary)", + logic: "nach (after) + schlagen = flip through pages after something", + exampleDe: "Mit dem Hover-Übersetzer musst du unbekannte Wörter nicht mehr mühsam nachschlagen.", + exampleEn: "With the hover translator, you no longer have to tediously look up unknown words.", + quizCloze: "Wenn ich den Artikel nicht weiß, ___ ich ihn kurz im Wörterbuch ___.", + quizAnswer: "schlage nach" + } + ] + }, + { + root: "kommen", + baseMeaning: "to come (kommt • kam • ist gekommen)", + derivatives: [ + { + word: "ankommen", + prefix: "an-", + separable: true, + forms: "kommt an • kam an • ist angekommen", + english: "to arrive (also: 'Es kommt darauf an' = it depends!)", + logic: "an (at) + kommen = arrive at destination", + exampleDe: "Unser ICE ist trotz der Baustelle pünktlich in Hamburg angekommen.", + exampleEn: "Our ICE train arrived on time in Hamburg despite the roadworks.", + quizCloze: "Um wie viel Uhr ___ dein Zug heute Abend am Hauptbahnhof ___?", + quizAnswer: "kommt an" + }, + { + word: "bekommen", + prefix: "be-", + separable: false, + forms: "bekommt • bekam • hat bekommen (FALSE FRIEND: means 'to get/receive', NOT 'become'!)", + english: "to get / to receive", + logic: "Inseparable be- + kommen: something comes to you", + exampleDe: "Ohne Anmeldung beim Bürgeramt bekommt man leider keine Steuer-ID.", + exampleEn: "Without registering at the civic office, you unfortunately don't get a tax ID.", + quizCloze: "Hast du meine Nachricht auf WhatsApp schon ___?", + quizAnswer: "bekommen" + }, + { + word: "vorbeikommen", + prefix: "vorbei-", + separable: true, + forms: "kommt vorbei • kam vorbei • ist vorbeigekommen", + english: "to drop by / come over / swing by", + logic: "vorbei (by/past) + kommen = come by someone's place", + exampleDe: "Wenn du Lust hast, kannst du heute Abend gerne auf ein Glas Wein vorbeikommen.", + exampleEn: "If you feel like it, you're welcome to drop by for a glass of wine tonight.", + quizCloze: "Sie können heute um elf Uhr direkt in der Praxis ___.", + quizAnswer: "vorbeikommen" + } + ] + } + ], + + compounds: [ + { + id: "comp1", + compound: "Krankenversicherungskarte", + finalArticle: "die", + plural: "die Krankenversicherungskarten", + english: "health insurance card", + parts: [ + { word: "Kranken-", article: null, meaning: "sick people's (from der/die Kranke)" }, + { word: "Versicherungs-", article: "die", meaning: "insurance (die Versicherung)" }, + { word: "Karte", article: "die", meaning: "card (die Karte → determines 'die'!)" } + ], + ruleNote: "Even though this word has 25 letters, the last building block is 'die Karte' (feminine), so the entire compound is 'die Krankenversicherungskarte'!", + exampleDe: "Bitte legen Sie am Empfang zuerst Ihre Krankenversicherungskarte vor." + }, + { + id: "comp2", + compound: "Wohnungsbesichtigung", + finalArticle: "die", + plural: "die Wohnungsbesichtigungen", + english: "apartment viewing", + parts: [ + { word: "Wohnungs-", article: "die", meaning: "apartment (die Wohnung + linking -s-)" }, + { word: "Besichtigung", article: "die", meaning: "viewing / inspection (die Besichtigung → determines 'die'!)" } + ], + ruleNote: "Notice the 'Fugen-s' (linking -s-) after -ung nouns when forming compounds: Wohnung + s + Besichtigung.", + exampleDe: "Am Samstagmittag gehen wir zusammen zu einer Wohnungsbesichtigung." + }, + { + id: "comp3", + compound: "Bürgeramt", + finalArticle: "das", + plural: "die Bürgerämter", + english: "citizens' registration office", + parts: [ + { word: "Bürger", article: "der", meaning: "citizen (der Bürger)" }, + { word: "Amt", article: "das", meaning: "office / department (das Amt → determines 'das'!)" } + ], + ruleNote: "'der Bürger' is masculine, but the final noun is 'das Amt' (neuter)—so it is ALWAYS 'das Bürgeramt'!", + exampleDe: "Ich habe online endlich einen freien Termin beim Bürgeramt gefunden." + }, + { + id: "comp4", + compound: "Kassenbon", + finalArticle: "der", + plural: "die Kassenbons", + english: "checkout receipt", + parts: [ + { word: "Kassen-", article: "die", meaning: "cash register (die Kasse)" }, + { word: "Bon", article: "der", meaning: "voucher / slip (der Bon → determines 'der'!)" } + ], + ruleNote: "'die Kasse' is feminine, but 'der Bon' is masculine—so the receipt is 'der Kassenbon'!", + exampleDe: "Bewahr den Kassenbon gut auf, falls wir das Gerät umtauschen müssen." + }, + { + id: "comp5", + compound: "Feierabendbier", + finalArticle: "das", + plural: "die Feierabendbiere", + english: "after-work beer", + parts: [ + { word: "Feier", article: "die", meaning: "celebration / rest (die Feier)" }, + { word: "Abend", article: "der", meaning: "evening (der Abend)" }, + { word: "Bier", article: "das", meaning: "beer (das Bier → determines 'das'!)" } + ], + ruleNote: "Three nouns with three different genders (die Feier + der Abend + das Bier) → last word wins: 'das Feierabendbier'!", + exampleDe: "Nach der langen Arbeitswoche trinken wir im Biergarten ein kühles Feierabendbier." + }, + { + id: "comp6", + compound: "Mehrwegbecher", + finalArticle: "der", + plural: "die Mehrwegbecher", + english: "reusable cup (with deposit)", + parts: [ + { word: "Mehrweg-", article: "der", meaning: "multi-way / reusable (mehr + der Weg)" }, + { word: "Becher", article: "der", meaning: "cup / mug (der Becher → determines 'der'!)" } + ], + ruleNote: "German contrasts 'Mehrweg' (reusable, literally 'more-way') with 'Einweg' (single-use/disposable, 'one-way').", + exampleDe: "Für den Mehrwegbecher auf dem Weihnachtsmarkt zahlt man zwei Euro Pfand." + }, + { + id: "comp7", + compound: "Nebenkostenabrechnung", + finalArticle: "die", + plural: "die Nebenkostenabrechnungen", + english: "annual utility bill statement", + parts: [ + { word: "Neben-", article: null, meaning: "additional / side" }, + { word: "Kosten-", article: "die (Pl.)", meaning: "costs (die Kosten)" }, + { word: "Abrechnung", article: "die", meaning: "settlement / statement (die Abrechnung → determines 'die'!)" } + ], + ruleNote: "Every tenant in Germany receives 'die Nebenkostenabrechnung' once a year comparing advance utility payments with actual heating/water usage.", + exampleDe: "Zum Glück mussten wir bei der Nebenkostenabrechnung dieses Jahr nichts nachzahlen." + }, + { + id: "comp8", + compound: "Anschlussverbindung", + finalArticle: "die", + plural: "die Anschlussverbindungen", + english: "connecting train / transit connection", + parts: [ + { word: "Anschluss-", article: "der", meaning: "connection / follow-up (der Anschluss)" }, + { word: "Verbindung", article: "die", meaning: "link / connection (die Verbindung → determines 'die'!)" } + ], + ruleNote: "'der Anschluss' is masculine, 'die Verbindung' is feminine → 'die Anschlussverbindung'.", + exampleDe: "Wegen der Verspätung warten viele Fahrgäste auf ihre Anschlussverbindung." + } + ] +}; + +// 2) LISTENING DICTATION & SHADOWING SENTENCES (HÖRTRAINING) +window.LISTENING_EXERCISES = [ + { + id: "listen1", + level: "A2", + situation: "Beim Arzt anrufen (Calling the doctor's office)", + de: "Ich möchte heute bitte kurzfristig einen Termin vereinbaren.", + en: "I would like to schedule an appointment on short notice today, please.", + focusNote: "Listen for 'kurzfristig' (at short notice) and the unstressed 'einen Termin'." + }, + { + id: "listen2", + level: "A2", + situation: "Termin verschieben (Postponing an appointment)", + de: "Leider muss ich unsere Besichtigung auf nächste Woche verschieben.", + en: "Unfortunately I have to postpone our viewing to next week.", + focusNote: "Notice the V2 inversion after 'Leider': 'Leider muss ich...' and the -ung ending on 'Besichtigung'." + }, + { + id: "listen3", + level: "A2", + situation: "An der Supermarktkasse (At the supermarket checkout)", + de: "Brauchen Sie den Kassenbon, oder haben Sie noch einen Pfandbon?", + en: "Do you need the receipt, or do you still have a bottle deposit slip?", + focusNote: "Two classic German checkout compounds: 'der Kassenbon' and 'der Pfandbon'." + }, + { + id: "listen4", + level: "A2 / B1", + situation: "Feierabend mit Kollegen (After work with colleagues)", + de: "Ich schlage vor, dass wir endlich Feierabend machen.", + en: "I suggest that we finally call it a day.", + focusNote: "Hear how the separable verb 'vorschlagen' splits in the main clause ('Ich schlage vor'), while 'machen' goes to the end after 'dass'." + }, + { + id: "listen5", + level: "A2 / B1", + situation: "Auf dem Bahnsteig (On the train platform)", + de: "Der Zug hat heute leider zwanzig Minuten Verspätung, deshalb müssen wir in Hannover umsteigen.", + en: "The train unfortunately has a twenty-minute delay today, therefore we have to transfer in Hanover.", + focusNote: "Notice the connector 'deshalb' followed immediately by the verb 'müssen'." + }, + { + id: "listen6", + level: "B1", + situation: "Wochenendausflug planen (Planning a weekend trip)", + de: "Keine Sorge, ich kümmere mich um die Unterkunft, obwohl es am Wochenende regnen soll.", + en: "No worries, I'll take care of the accommodation, even though it's supposed to rain on the weekend.", + focusNote: "Listen for 'ich kümmere mich um' (+ Accusative) and 'obwohl' kicking 'regnen soll' to the very end." + }, + { + id: "listen7", + level: "A2", + situation: "Kurze Nachricht an Freunde (Quick message to friends)", + de: "Gibst du mir bitte kurz Bescheid, sobald du zu Hause angekommen bist?", + en: "Will you please let me know briefly as soon as you have arrived home?", + focusNote: "Natural everyday idiom 'Bescheid geben' + subordinate clause connector 'sobald'." + }, + { + id: "listen8", + level: "B1", + situation: "Reklamation im Kaufhaus (Exchanging an item at a store)", + de: "Ich möchte diese Jacke gerne umtauschen, weil der Reißverschluss kaputt ist.", + en: "I would like to exchange this jacket because the zipper is broken.", + focusNote: "Notice 'diese Jacke umtauschen' and 'der Reißverschluss' (zipper)." + } +]; + +// 3) VERBS WITH PREPOSITIONS & CASES (REKTION DER VERBEN + DA-/WO- TRAINER) +window.PREPOSITION_DRILLS = [ + { + id: "prep1", + verb: "sich kümmern", + preposition: "um", + grammaticalCase: "Akkusativ", + daForm: "darum", + woForm: "worum", + english: "to take care of / look after", + sentenceBefore: "Keine Sorge, ich kümmere mich heute", + sentenceAfter: "Abendessen.", + nounHint: "das Abendessen (neut.)", + correctCombo: "um das", + acceptedAnswers: ["um das", "ums"], + options: ["um das", "für das", "über das", "mit dem"], + daExampleDe: "Wir brauchen noch Getränke. — Ich kümmere mich darum!", + explanation: "'sich kümmern' ALWAYS takes 'um + Akkusativ' (um das Abendessen / ums Abendessen). For things: 'darum' / 'Worum kümmerst du dich?'" + }, + { + id: "prep2", + verb: "sich freuen (Zukunft)", + preposition: "auf", + grammaticalCase: "Akkusativ", + daForm: "darauf", + woForm: "worauf", + english: "to look forward to (something in the future)", + sentenceBefore: "Nach der langen Arbeitswoche freue ich mich riesig", + sentenceAfter: "Feierabend!", + nounHint: "der Feierabend (mask.)", + correctCombo: "auf den", + acceptedAnswers: ["auf den"], + options: ["auf den", "auf dem", "über den", "für den"], + daExampleDe: "Am Freitag fahren wir ans Meer — ich freue mich schon sehr darauf!", + explanation: "Future events take 'sich freuen AUF + Akkusativ'. Since 'der Feierabend' is masculine, Accusative changes 'der' to 'den' → 'auf den Feierabend'." + }, + { + id: "prep3", + verb: "sich freuen (Gegenwart/Vergangenheit)", + preposition: "über", + grammaticalCase: "Akkusativ", + daForm: "darüber", + woForm: "worüber", + english: "to be happy about (something received or already happening)", + sentenceBefore: "Sie hat sich gestern sehr", + sentenceAfter: "nette Einladung gefreut.", + nounHint: "die Einladung (fem.)", + correctCombo: "über die", + acceptedAnswers: ["über die", "ueber die"], + options: ["über die", "auf die", "über der", "von der"], + daExampleDe: "Du hast mir sehr geholfen — ich habe mich wirklich darüber gefreut.", + explanation: "When something has already happened or you received a gift/invitation, use 'sich freuen ÜBER + Akkusativ' ('über die Einladung')." + }, + { + id: "prep4", + verb: "teilnehmen", + preposition: "an", + grammaticalCase: "Dativ", + daForm: "daran", + woForm: "woran", + english: "to participate in / attend", + sentenceBefore: "Möchtest du nächste Woche auch", + sentenceAfter: "Deutschkurs teilnehmen?", + nounHint: "der Deutschkurs (mask.)", + correctCombo: "an dem", + acceptedAnswers: ["an dem", "am"], + options: ["an dem (am)", "in dem", "auf den", "zu dem"], + daExampleDe: "Morgen findet ein Workshop statt. Nimmst du auch daran teil?", + explanation: "'teilnehmen' takes 'an + Dativ'! Masculine 'der Deutschkurs' becomes 'dem' in Dative → 'an dem / am Deutschkurs'." + }, + { + id: "prep5", + verb: "abhängen", + preposition: "von", + grammaticalCase: "Dativ", + daForm: "davon", + woForm: "wovon", + english: "to depend on", + sentenceBefore: "Ob wir im Park grillen können, hängt natürlich stark", + sentenceAfter: "Wetter ab.", + nounHint: "das Wetter (neut.)", + correctCombo: "vom", + acceptedAnswers: ["vom", "von dem"], + options: ["vom (von dem)", "auf das", "über das", "mit dem"], + daExampleDe: "Kommst du heute Abend mit? — Das hängt davon ab, wann ich Feierabend habe.", + explanation: "'abhängen' takes 'von + Dativ' (von dem Wetter = vom Wetter). Remember: 'von' is ALWAYS Dative in German!" + }, + { + id: "prep6", + verb: "warten", + preposition: "auf", + grammaticalCase: "Akkusativ", + daForm: "darauf", + woForm: "worauf", + english: "to wait for", + sentenceBefore: "Auf dem Bahnsteig warten wir schon seit zwanzig Minuten", + sentenceAfter: "Zug nach Hamburg.", + nounHint: "der Zug (mask.)", + correctCombo: "auf den", + acceptedAnswers: ["auf den"], + options: ["auf den", "für den", "auf dem", "nach dem"], + daExampleDe: "Mein neuer Reisepass ist noch nicht da; ich warte schon drei Wochen darauf.", + explanation: "English says 'wait FOR', but German NEVER uses 'für' with warten! It is always 'warten AUF + Akkusativ' ('auf den Zug')." + }, + { + id: "prep7", + verb: "sich gewöhnen", + preposition: "an", + grammaticalCase: "Akkusativ", + daForm: "daran", + woForm: "woran", + english: "to get used to / accustomed to", + sentenceBefore: "Nach ein paar Monaten habe ich mich schnell", + sentenceAfter: "ruhigen Sonntage in Deutschland gewöhnt.", + nounHint: "die Sonntage (Plural)", + correctCombo: "an die", + acceptedAnswers: ["an die"], + options: ["an die", "zu den", "mit den", "an den"], + daExampleDe: "Am Anfang war die deutsche Bürokratie ungewohnt, aber man gewöhnt sich daran.", + explanation: "'sich gewöhnen' takes 'an + Akkusativ' (moving toward a new habit → Accusative 'an die Sonntage')." + }, + { + id: "prep8", + verb: "bitten", + preposition: "um", + grammaticalCase: "Akkusativ", + daForm: "darum", + woForm: "worum", + english: "to ask for / request politely", + sentenceBefore: "Wegen der Verspätung bitten wir alle Fahrgäste", + sentenceAfter: "Verständnis.", + nounHint: "das Verständnis (neut.)", + correctCombo: "um das", + acceptedAnswers: ["um", "um das", "um ihr"], + options: ["um das (um Ihr)", "für das", "nach dem", "über das"], + daExampleDe: "Kannst du mir beim Umzug helfen? Ich wollte dich schon gestern darum bitten.", + explanation: "'bitten UM + Akkusativ' means 'to ask FOR something' ('Wir bitten um Ihr Verständnis'). Compare with 'fragen nach + Dativ' (to ask about information)." + }, + { + id: "prep9", + verb: "sich interessieren", + preposition: "für", + grammaticalCase: "Akkusativ", + daForm: "dafür", + woForm: "wofür", + english: "to be interested in", + sentenceBefore: "Bei der Besichtigung haben sich über dreißig Personen", + sentenceAfter: "Wohnung interessiert.", + nounHint: "die Wohnung (fem.)", + correctCombo: "für die", + acceptedAnswers: ["für die", "fuer die"], + options: ["für die", "in der", "an der", "über die"], + daExampleDe: "Wofür interessierst du dich besonders? — Für deutsche Geschichte und Kultur!", + explanation: "English says 'interested IN', but German says 'sich interessieren FÜR + Akkusativ' ('für die Wohnung')." + }, + { + id: "prep10", + verb: "sich erinnern", + preposition: "an", + grammaticalCase: "Akkusativ", + daForm: "daran", + woForm: "woran", + english: "to remember / recall", + sentenceBefore: "Erinnerst du dich noch", + sentenceAfter: "unseren ersten Ausflug nach München?", + nounHint: "der Ausflug (mask., 'unseren' = Akk.)", + correctCombo: "an", + acceptedAnswers: ["an"], + options: ["an", "über", "von", "auf"], + daExampleDe: "Ja, natürlich erinnere ich mich noch sehr gut daran!", + explanation: "'sich erinnern AN + Akkusativ' = to remember. Notice how 'daran' replaces 'an unseren ersten Ausflug'." + } +]; diff --git a/index.html b/index.html index f60ef4a..703d8a3 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ - + @@ -30,9 +30,18 @@ 📊 Übersicht + + + @@ -68,7 +77,7 @@

After 1,400 days on Duolingo, you already have a strong intuition for basic German structure. WortKraft bridges the A2→B1 plateau by training active recall with articles, - compound word logic, and real-world production. + compound word logic, verb + preposition cases, and native listening & production.

der • Maskulin @@ -81,8 +90,8 @@ -
@@ -99,26 +108,26 @@
0 gemeistert • 0 im Training
-
Artikel-Trefferquote
+
Artikel- & Übungsquote
—
-
der / die / das & aktive Eingabe
+
der / die / das & Präpositionen
-
Aktive Sätze geschrieben
+
Aktive Sätze produziert
0
-
In der Sprachpraxis produziert
+
Sprachpraxis & Hörtraining
-

Dein täglicher 3-Schritte-Workflow

+

Deine 6 Trainings-Module (A2 → B1)

-
🎯
+
⚡
1. Aktiver Abruf im Kontext (SRS-Trainer)
Lückensätze, Englisch → Deutsch mit Artikel & Plural-Drill statt Multiple-Choice.
@@ -127,12 +136,45 @@ →
+
+
+
🧱
+
+
2. Wortbaukasten (Komposita & Präfix-Labor)
+
Verstehe trennbare/untrennbare Verben (nehmen, stellen, kommen) & lange zusammengesetzte Nomen.
+
+
+ → +
+ +
+
+
🎯
+
+
3. Verben mit Präposition & Kasus (Rektion + Da-/Wo-)
+
Meistere warten auf (+Akk), teilnehmen an (+Dat), sich kümmern um (+Akk) & darauf/worauf.
+
+
+ → +
+ +
+
+
🎧
+
+
4. Hörtraining & Aussprache-Check (Diktat & Mikrofon)
+
Höre echte Alltagssätze ohne Text, tippe was du hörst, oder sprich den Satz selbst ins Mikrofon.
+
+
+ → +
+
📖
-
2. Interaktive Leseecke (A2/B1 Geschichten & Alltag)
-
Klicke auf jedes Wort für Artikel, Stammform, Audio & 1-Klick-Speichern ins SRS-Deck.
+
5. Interaktive Leseecke (A2/B1 Geschichten & Alltag)
+
Hover-Übersetzer + Klick auf jedes Wort für Artikel, Stammform, Audio & 1-Klick-SRS-Speichern.
→ @@ -142,7 +184,7 @@
💬
-
3. Sprachpraxis mit Zielwörtern
+
6. Sprachpraxis mit Zielwörtern
Löse echte Alltagssituationen (Arzt, Bürgeramt, Feierabend) und nutze gezielt 5 Zielwörter.
@@ -197,7 +239,48 @@
- + +
+
+
+ + + +
+
+
+
+ + +
+
+
+ + + +
+
+
+
+ + +
+
+
+ +
- +
- +
@@ -408,10 +491,11 @@
- - - - - + + + + + + diff --git a/styles.css b/styles.css index 838306d..678ba32 100644 --- a/styles.css +++ b/styles.css @@ -1125,3 +1125,140 @@ body.hover-translate-on .word-token:hover { margin-top: 0.15rem; } +/* === WORTBAUKASTEN (COMPOUND & PREFIX LAB) === */ +.compound-blocks-row { + display: flex; + align-items: stretch; + gap: 0.5rem; + flex-wrap: wrap; + margin: 1rem 0; +} + +.compound-block { + background: var(--bg-main); + border: 2px solid var(--border-strong); + border-radius: 12px; + padding: 0.75rem 1rem; + display: flex; + flex-direction: column; + gap: 0.2rem; + min-width: 130px; +} + +.compound-block.head-word { + border-color: var(--primary); + background: #fffbeb; + box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.12); +} + +.compound-plus { + display: flex; + align-items: center; + font-weight: 800; + font-size: 1.25rem; + color: var(--text-muted); +} + +.prefix-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); + gap: 1rem; + margin-top: 1rem; +} + +.prefix-card { + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 1.15rem; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.sep-pill { + font-size: 0.72rem; + font-weight: 700; + padding: 0.15rem 0.55rem; + border-radius: 999px; +} + +.sep-yes { + background: #ecfdf5; + color: #047857; + border: 1px solid #6ee7b7; +} + +.sep-no { + background: #eff6ff; + color: #1d4ed8; + border: 1px solid #93c5fd; +} + +/* === HÖRTRAINING (LISTENING DICTATION & SHADOWING) === */ +.audio-hero-box { + background: linear-gradient(135deg, #1e1b4b 0%, #312e81 100%); + color: #fff; + border-radius: var(--radius-md); + padding: 1.5rem; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + flex-wrap: wrap; + margin-bottom: 1.25rem; +} + +.diff-word { + display: inline-block; + padding: 0.15rem 0.45rem; + border-radius: 6px; + margin: 0.12rem; + font-weight: 700; +} + +.diff-ok { + background: #d1fae5; + color: #065f46; +} + +.diff-miss { + background: #fee2e2; + color: #991b1b; + text-decoration: underline wavy; +} + +.mic-btn-recording { + background: #dc2626 !important; + color: #fff !important; + animation: pulseMic 1.2s infinite; +} + +@keyframes pulseMic { + 0% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.55); } + 70% { box-shadow: 0 0 0 10px rgba(220, 38, 38, 0); } + 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0); } +} + +/* === PREPOSITION & CASE TRAINER === */ +.case-badge-akk { + background: #fef3c7; + color: #b45309; + border: 1px solid #fcd34d; + font-weight: 700; + font-size: 0.76rem; + padding: 0.15rem 0.55rem; + border-radius: 6px; +} + +.case-badge-dat { + background: #ede9fe; + color: #6d28d9; + border: 1px solid #c4b5fd; + font-weight: 700; + font-size: 0.76rem; + padding: 0.15rem 0.55rem; + border-radius: 6px; +} + +