Lehrer-Observability + Weltküche-Inhalt + Wrapper-Fix + Passstraße

teacher.html: Menü „Live" → „Ergebnisse" mit Unteransichten
Tag·Aktuell·Vergleich·Gesamt (alte Ergebnisse-Ansicht ist jetzt „Gesamt").
Neue Kennzahl Qualität (grafischer richtig/falsch-Balken) in Aktuell +
Vergleich + Weltküche-Zeile, Gerichte-Zähler (Fleiß), Labels entschärft
(„Kritisch" → Stark/Solide/Viele Fehler).

Weltküche: korrekte Artikel (der/die/das) für alle 70 Zutaten in
production-matrix.json; verdrehten Herkunfts-Satz + Heimat-Banner neu und
marktbewusst (Ukraine-Distraktor ehrlich erklärt), „man"-Konstruktionen
für Singular/Plural.

_scripts.php: renderPage() injizierte Favicon per strrpos ins letzte
</head> — das lag in teacher.htmls printBatchTickets-JS-String → SyntaxError
zerschoss das ganze Inline-Script auf /teacher. Fix: strpos (erstes </head>).

tourismusregion: neue Karte passstrasse in maps-custom.json (Route bergauf
136 Punkte, 41 Bauslots) aus Editor-Export.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 13:32:24 +02:00
parent 4bfb6539cb
commit 5655af81bf
6 changed files with 7038 additions and 5808 deletions
@@ -1,6 +1,7 @@
{
"pfeffer": {
"nm": "Schwarzer Pfeffer",
"art": "der",
"ic": "🧂",
"producers": {
"vietnam": {
@@ -49,6 +50,7 @@
},
"kakao": {
"nm": "Kakao",
"art": "der",
"ic": "🍫",
"producers": {
"elfenbein": {
@@ -105,6 +107,7 @@
},
"vanille": {
"nm": "Vanille",
"art": "die",
"ic": "🌼",
"producers": {
"madagaskar": {
@@ -136,6 +139,7 @@
},
"kurkuma": {
"nm": "Kurkuma",
"art": "die",
"ic": "🟡",
"producers": {
"indien": {
@@ -184,6 +188,7 @@
},
"ingwer": {
"nm": "Ingwer",
"art": "der",
"ic": "🫚",
"producers": {
"indien": {
@@ -235,6 +240,7 @@
},
"zimt": {
"nm": "Zimt",
"art": "der",
"ic": "🪵",
"producers": {
"indonesien": {
@@ -270,6 +276,7 @@
},
"kardamom": {
"nm": "Kardamom",
"art": "der",
"ic": "🫛",
"producers": {
"guatemala": {
@@ -305,6 +312,7 @@
},
"sesam": {
"nm": "Sesam",
"art": "der",
"ic": "⚪",
"producers": {
"sudan": {
@@ -356,6 +364,7 @@
},
"chili": {
"nm": "Chili",
"art": "die",
"ic": "🌶️",
"producers": {
"indien": {
@@ -403,6 +412,7 @@
},
"kumin": {
"nm": "Kreuzkümmel (Cumin)",
"art": "der",
"ic": "🌿",
"producers": {
"indien": {
@@ -437,6 +447,7 @@
},
"koriander": {
"nm": "Koriander (Samen)",
"art": "der",
"ic": "🌿",
"producers": {
"indien": {
@@ -481,6 +492,7 @@
},
"safran": {
"nm": "Safran",
"art": "der",
"ic": "🌸",
"producers": {
"iran": {
@@ -519,6 +531,7 @@
},
"muskat": {
"nm": "Muskat",
"art": "der",
"ic": "🌰",
"producers": {
"indonesien": {
@@ -548,6 +561,7 @@
},
"nelken": {
"nm": "Gewürznelken",
"art": "die",
"ic": "🌾",
"producers": {
"indonesien": {
@@ -577,6 +591,7 @@
},
"paprika": {
"nm": "Paprika-Pulver",
"art": "das",
"ic": "🟥",
"producers": {
"china": {
@@ -626,6 +641,7 @@
},
"kuemmel": {
"nm": "Kümmel",
"art": "der",
"ic": "🌿",
"producers": {
"finnland": {
@@ -668,6 +684,7 @@
},
"majoran": {
"nm": "Majoran",
"art": "der",
"ic": "🌿",
"producers": {
"aegypten": {
@@ -704,6 +721,7 @@
},
"kraeuter": {
"nm": "Mediterrane Kräuter",
"art": "die",
"ic": "🌿",
"producers": {
"marokko": {
@@ -759,6 +777,7 @@
},
"banane": {
"nm": "Banane",
"art": "die",
"ic": "🍌",
"producers": {
"indien": {
@@ -832,6 +851,7 @@
},
"avocado": {
"nm": "Avocado",
"art": "die",
"ic": "🥑",
"producers": {
"mexiko": {
@@ -894,6 +914,7 @@
},
"limette": {
"nm": "Limette",
"art": "die",
"ic": "🟢",
"producers": {
"mexiko": {
@@ -953,6 +974,7 @@
},
"orange": {
"nm": "Orange / Orangensaft",
"art": "die",
"ic": "🍊",
"producers": {
"brasilien": {
@@ -1029,6 +1051,7 @@
},
"zitrone": {
"nm": "Zitrone",
"art": "die",
"ic": "🍋",
"producers": {
"indien": {
@@ -1102,6 +1125,7 @@
},
"kokos": {
"nm": "Kokosnuss / Kokosmilch",
"art": "die",
"ic": "🥥",
"producers": {
"indonesien": {
@@ -1153,6 +1177,7 @@
},
"tamarinde": {
"nm": "Tamarinde",
"art": "die",
"ic": "🟤",
"producers": {
"indien": {
@@ -1187,6 +1212,7 @@
},
"kaffee": {
"nm": "Kaffee",
"art": "der",
"ic": "☕",
"producers": {
"brasilien": {
@@ -1244,6 +1270,7 @@
},
"wein": {
"nm": "Wein (Reben)",
"art": "der",
"ic": "🍷",
"producers": {
"italien": {
@@ -1322,6 +1349,7 @@
},
"reis": {
"nm": "Reis",
"art": "der",
"ic": "🍚",
"producers": {
"china": {
@@ -1420,6 +1448,7 @@
},
"reisnudeln": {
"nm": "Reisnudeln",
"art": "die",
"ic": "🍜",
"producers": {
"china": {
@@ -1461,6 +1490,7 @@
},
"hartweizen": {
"nm": "Hartweizen (Durum)",
"art": "der",
"ic": "🌾",
"producers": {
"kanada": {
@@ -1527,6 +1557,7 @@
},
"mehl": {
"nm": "Mehl (Weichweizen)",
"art": "das",
"ic": "🌾",
"producers": {
"china": {
@@ -1615,6 +1646,7 @@
},
"mais": {
"nm": "Mais (Tortilla, Polenta)",
"art": "der",
"ic": "🌽",
"producers": {
"usa": {
@@ -1711,6 +1743,7 @@
},
"mandeln": {
"nm": "Mandeln",
"art": "die",
"ic": "🌰",
"producers": {
"usa": {
@@ -1771,6 +1804,7 @@
},
"erdnuss": {
"nm": "Erdnüsse",
"art": "die",
"ic": "🥜",
"producers": {
"china": {
@@ -1846,6 +1880,7 @@
},
"kichererbsen": {
"nm": "Kichererbsen",
"art": "die",
"ic": "🟤",
"producers": {
"indien": {
@@ -1911,6 +1946,7 @@
},
"soja": {
"nm": "Sojabohnen",
"art": "die",
"ic": "🫘",
"producers": {
"brasilien": {
@@ -1990,6 +2026,7 @@
},
"soja-sauce": {
"nm": "Sojasauce",
"art": "die",
"ic": "🥢",
"producers": {
"china": {
@@ -2028,6 +2065,7 @@
},
"rohrzucker": {
"nm": "Rohrzucker",
"art": "der",
"ic": "🧊",
"producers": {
"brasilien": {
@@ -2100,6 +2138,7 @@
},
"apfel": {
"nm": "Apfel",
"art": "der",
"ic": "🍎",
"producers": {
"china": {
@@ -2223,6 +2262,7 @@
},
"marille": {
"nm": "Marille (Aprikose)",
"art": "die",
"ic": "🍑",
"producers": {
"tuerkei": {
@@ -2296,6 +2336,7 @@
},
"kirschen": {
"nm": "Kirschen",
"art": "die",
"ic": "🍒",
"producers": {
"tuerkei": {
@@ -2374,6 +2415,7 @@
},
"lebkuchen": {
"nm": "Lebkuchen-Gewürz",
"art": "das",
"ic": "🍪",
"producers": {
"indonesien": {
@@ -2409,6 +2451,7 @@
},
"rosinen": {
"nm": "Rosinen (getr. Trauben)",
"art": "die",
"ic": "🍇",
"producers": {
"tuerkei": {
@@ -2463,6 +2506,7 @@
},
"olivenoel": {
"nm": "Olivenöl",
"art": "das",
"ic": "🫒",
"producers": {
"spanien": {
@@ -2522,6 +2566,7 @@
},
"milch": {
"nm": "Milch / Sahne",
"art": "die",
"ic": "🥛",
"producers": {
"indien": {
@@ -2658,6 +2703,7 @@
},
"butter": {
"nm": "Butter",
"art": "die",
"ic": "🧈",
"producers": {
"indien": {
@@ -2749,6 +2795,7 @@
},
"feta": {
"nm": "Feta (Käse)",
"art": "der",
"ic": "🧀",
"producers": {
"griechenland": {
@@ -2781,6 +2828,7 @@
},
"mozzarella": {
"nm": "Mozzarella",
"art": "der",
"ic": "🧀",
"producers": {
"italien": {
@@ -2827,6 +2875,7 @@
},
"pecorino": {
"nm": "Pecorino (Käse)",
"art": "der",
"ic": "🧀",
"producers": {
"italien": {
@@ -2857,6 +2906,7 @@
},
"topfen": {
"nm": "Topfen / Quark",
"art": "der",
"ic": "🥛",
"producers": {
"deutschland": {
@@ -2911,6 +2961,7 @@
},
"schmand": {
"nm": "Schmand / Saure Sahne",
"art": "der",
"ic": "🥛",
"producers": {
"deutschland": {
@@ -2958,6 +3009,7 @@
},
"fleisch": {
"nm": "Fleisch (Kalb/Schwein/Rind, regional)",
"art": "das",
"ic": "🥩",
"producers": {
"oesterreich": {
@@ -3032,6 +3084,7 @@
},
"lamm": {
"nm": "Lammfleisch",
"art": "das",
"ic": "🐑",
"producers": {
"tuerkei": {
@@ -3123,6 +3176,7 @@
},
"huhn-spanien": {
"nm": "Hähnchen / Huhn (Paella)",
"art": "das",
"ic": "🐔",
"producers": {
"spanien": {
@@ -3166,6 +3220,7 @@
},
"rind-ungarn": {
"nm": "Rind (für Gulasch)",
"art": "das",
"ic": "🥩",
"producers": {
"ungarn": {
@@ -3215,6 +3270,7 @@
},
"speck": {
"nm": "Speck (Pancetta/Tiroler)",
"art": "der",
"ic": "🥓",
"producers": {
"italien": {
@@ -3268,6 +3324,7 @@
},
"speck-lorraine": {
"nm": "Lardons (für Quiche)",
"art": "die",
"ic": "🥓",
"producers": {
"frankreich": {
@@ -3299,6 +3356,7 @@
},
"eier": {
"nm": "Eier",
"art": "die",
"ic": "🥚",
"producers": {
"china": {
@@ -3397,6 +3455,7 @@
},
"fischsauce": {
"nm": "Fischsauce",
"art": "die",
"ic": "🐟",
"producers": {
"vietnam": {
@@ -3453,6 +3512,7 @@
},
"nori": {
"nm": "Nori (Seetang)",
"art": "der",
"ic": "🟢",
"producers": {
"china": {
@@ -3500,6 +3560,7 @@
},
"wasabi": {
"nm": "Wasabi (echt)",
"art": "der",
"ic": "🟢",
"producers": {
"japan": {
@@ -3541,6 +3602,7 @@
},
"tomaten": {
"nm": "Tomaten",
"art": "die",
"ic": "🍅",
"producers": {
"china": {
@@ -3632,6 +3694,7 @@
},
"gemuese": {
"nm": "Sommer-Gemüse (Mittelmeer)",
"art": "das",
"ic": "🥬",
"producers": {
"spanien": {
@@ -3681,6 +3744,7 @@
},
"wurzelgemuese": {
"nm": "Wurzelgemüse (Möhre, Sellerie, Pastinake)",
"art": "das",
"ic": "🥕",
"producers": {
"china": {
@@ -3749,6 +3813,7 @@
},
"kartoffel": {
"nm": "Kartoffel",
"art": "die",
"ic": "🥔",
"producers": {
"china": {
@@ -3885,6 +3950,7 @@
},
"zwiebel": {
"nm": "Zwiebel",
"art": "die",
"ic": "🧅",
"producers": {
"china": {
@@ -3978,6 +4044,7 @@
},
"knoblauch": {
"nm": "Knoblauch",
"art": "der",
"ic": "🧄",
"producers": {
"china": {
@@ -4056,6 +4123,7 @@
},
"champignons": {
"nm": "Champignons",
"art": "die",
"ic": "🍄",
"producers": {
"china": {
@@ -4140,6 +4208,7 @@
},
"hefe": {
"nm": "Hefe",
"art": "die",
"ic": "🫧",
"producers": {
"frankreich": {
@@ -4190,6 +4259,7 @@
},
"essig": {
"nm": "Essig (Wein- / Apfelessig)",
"art": "der",
"ic": "🧪",
"producers": {
"italien": {
@@ -4241,4 +4311,4 @@
],
"fact": "Aceto Balsamico Tradizionale di Modena reift mindestens 12 Jahre in Holzfässern — eine kleine Flasche kann über 100 € kosten."
}
}
}
+26 -7
View File
@@ -521,7 +521,7 @@ async function loadWeltkuecheData() {
// ING-Map aus production-matrix bauen
Object.entries(prodMatrix).forEach(([k, v]) => {
ING[k] = {
nm: v.nm, ic: v.ic,
nm: v.nm, ic: v.ic, art: v.art || 'die',
producers: v.producers || {},
climate_possible: v.climate_possible || [],
fact: v.fact || '',
@@ -1021,6 +1021,16 @@ function impossibleCountries(corr, possible) {
return out;
}
// Zutat mit korrektem Artikel: „die Kartoffel", „der Pfeffer", „das Olivenöl".
// Plural-Zutaten tragen art='die' — die Sätze nutzen bewusst „man"-Konstruktionen
// (nimmt man / holt man …), damit Singular UND Plural grammatisch passen.
function ingWas(ing, sTask, ingKey) {
const label = sTask && sTask.label;
if (label) return label;
const a = (ing && ing.art) || 'die';
return a + ' ' + (ing ? ing.nm : '');
}
function buildTaskFor(ingKey) {
if (_taskCache[ingKey]) return _taskCache[ingKey];
const ing = ING[ingKey];
@@ -1358,12 +1368,17 @@ function explainChoice(ingKey, key, isCorrect){
const sTask = _taskCache[ingKey];
if (sTask && sTask.signature) {
const heimatN = C[sTask.heimat] ? C[sTask.heimat].n : '';
const was = sTask.label || ('der/die/das ' + ing.nm);
const was = ingWas(ing, sTask, ingKey);
if (isCorrect) {
return {cls:'ok', badge:'✓', text:`Dieses Gericht kommt aus <b>${heimatN}</b> ${was} ist hier heimisch und wird vor Ort erzeugt.`};
if (key === sTask.heimat)
return {cls:'ok', badge:'✓', text:`Richtig für ein Gericht aus <b>${heimatN}</b> nimmt man ${was} aus ${heimatN} selbst.`};
return {cls:'ok', badge:'✓', text:`Auch richtig ${heimatN} allein deckt den Bedarf nicht, darum ist ${C[key].n} als Nachbarland ein realistischer Zweit-Lieferant.`};
}
if (info) {
return {cls:'mid', badge:'⚠️', text:`${C[key].n} erzeugt zwar viel ${ing.nm}${amount?' ('+amount+')':''} aber in einem Gericht aus ${heimatN} stammt ${was} von dort.`};
const m = info.market || 'global';
if (m === 'world-far' || m === 'local')
return {cls:'mid', badge:'🌐', text:`${C[key].n} erzeugt zwar riesige Mengen ${ing.nm}${amount?' ('+amount+')':''} in unseren Handel kommt davon aber kaum etwas. Für ein Gericht aus ${heimatN} nimmt man ${was} aus ${heimatN} oder einem Nachbarland.`};
return {cls:'mid', badge:'⚠️', text:`${C[key].n} ist auch ein echter Erzeuger${amount?' ('+amount+')':''} aber für ein Gericht aus ${heimatN} nimmt man ${was} lieber aus ${heimatN} selbst oder dem nächsten Nachbarland.`};
}
// Nicht-Produzent-Fehlklick → normale „unmöglich"-Logik unten
}
@@ -1471,7 +1486,7 @@ function showSolved(ing,pts,bonus){
const factLine = ing.fact ? `<div class="more-line"><b>Wusstest du?</b> ${esc(ing.fact)}</div>` : '';
// Heimat-Regel: erklären, warum die Region die Antwort ist (nicht der größte Produzent)
const sigLine = (task.signature && C[task.heimat])
? `<div class="more-line" style="background:#eef5ec;border-left:3px solid #4a7c4e">🍽️ Das ist ein Gericht aus <b>${C[task.heimat].n}</b>. ${task.label ? ('<b>'+task.label+'</b>') : ('Der/die/das '+esc(ing.nm))} kommt von hier nur Zutaten, die bei uns gar nicht wachsen, reisen von weit her.</div>`
? `<div class="more-line" style="background:#eef5ec;border-left:3px solid #4a7c4e">🍽️ Das ist ein Gericht aus <b>${C[task.heimat].n}</b>. Zutaten werden zwar bevorzugt aus ${C[task.heimat].n} verwendet, aber ${C[task.heimat].n} allein deckt den Bedarf nicht ab darum zählt auch ein Nachbarland als richtig. Nur Zutaten, die bei uns gar nicht wachsen, reisen von weit her.</div>`
: '';
// Caveats für world-far/off-season Korrekt-Picks (pro Land separat)
const caveats = task.correct.map(k => {
@@ -1521,8 +1536,12 @@ function showWrong(key, kind, ingKey){
const info = ing.producers[key];
const amount = info && info.t ? fmtTonnes(info.t) : 'verbreitet';
const heimatN = C[sTask.heimat] ? C[sTask.heimat].n : '';
const was = sTask.label || ('der/die/das ' + ing.nm);
card.innerHTML = `<div class="rc-head">⚠️ ${c.f} ${c.n} erzeugt zwar viel ${ing.nm} (${amount}) aber dieses Gericht kommt aus ${heimatN}, und ${was} stammt von dort.</div>`+
const was = ingWas(ing, sTask, ingKey);
const m = info.market || 'global';
const head = (m === 'world-far' || m === 'local')
? `⚠️ ${c.f} ${c.n} erzeugt zwar riesige Mengen ${ing.nm} (${amount}) aber davon kommt bei uns fast nichts in den Handel. Für dieses Gericht aus ${heimatN} nimmt man ${was} aus ${heimatN} oder einem Nachbarland.`
: `⚠️ ${c.f} ${c.n} ist auch ein echter Erzeuger (${amount}) aber für dieses Gericht aus ${heimatN} nimmt man ${was} lieber aus ${heimatN} selbst oder dem nächsten Nachbarland.`;
card.innerHTML = `<div class="rc-head">${head}</div>`+
`<div class="note">${c.info}<br><br>🔎 Tipp: Achte auf den Namen des Gerichts er verrät oft die Herkunft.</div>`;
return;
}