Weltküche: Heimat-Regel – Zutaten folgen dem Gericht statt Zufall
Löst "warum kommt Deutschland nicht vor?": In regionalen Gerichten kommt jede Zutat, die das Herkunftsland selbst erzeugt, von dort (Tiroler Gröstl → Tiroler Speck/Kartoffeln aus Österreich). Nur was hier nicht wächst (Pfeffer, Olivenöl) reist von weit her – die eigentliche Lektion. Datengetrieben: Test "erzeugt das Heimatland die Zutat?" filtert automatisch, kein Länder-Bias (hängt am Gericht). - dishes.json: heimat (25 Gerichte) + signature-Labels (5); exotische ohne heimat - buildTaskFor: Heimat-Regel sticht Zufall aus, wenn Heimatland Produzent ist - Klick-Feedback beantwortet "warum nicht Deutschland?" direkt (showWrong/explainChoice) - Auflösung erklärt Heimat-Logik + zeigt Antwort auch wenn kein Top-5-Produzent Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -984,6 +984,30 @@ function buildTaskFor(ingKey) {
|
||||
if (_taskCache[ingKey]) return _taskCache[ingKey];
|
||||
const ing = ING[ingKey];
|
||||
if (!ing) return null;
|
||||
// HEIMAT-REGEL: In einem regionalen Gericht kommt jede Zutat, die das
|
||||
// Herkunftsland selbst erzeugt, von dort — logisch nachvollziehbar (ein
|
||||
// Tiroler Gröstl nutzt Tiroler Speck, Tiroler Kartoffeln …). Der Test
|
||||
// „erzeugt das Heimatland diese Zutat?" filtert automatisch: Österreich
|
||||
// baut Kartoffeln an (→ Österreich), aber keinen Pfeffer und kein Olivenöl
|
||||
// (→ dort greift die normale Welt-Logik weiter unten). Kein Länder-Bias,
|
||||
// weil die Antwort am Gericht hängt, nicht am Standort der App.
|
||||
const _hDish = current && current.dish;
|
||||
const heimat = _hDish && _hDish.heimat;
|
||||
if (heimat && C[heimat] && ing.producers && ing.producers[heimat]) {
|
||||
const correct = [heimat];
|
||||
const others = Object.entries(ing.producers)
|
||||
.filter(([c]) => C[c] && c !== heimat)
|
||||
.sort((a, b) => (b[1].t || 0) - (a[1].t || 0))
|
||||
.map(([c]) => c);
|
||||
const climatePossible = (ing.climate_possible || []).filter(c => C[c] && c !== heimat);
|
||||
const distr = others.slice(0, 3);
|
||||
if (climatePossible.length && distr.length < 3) distr.push(climatePossible[0]);
|
||||
const choices = [...correct, ...distr];
|
||||
shuffleInPlace(choices);
|
||||
const label = (_hDish.signature && _hDish.signature[ingKey]) || null;
|
||||
_taskCache[ingKey] = { correct, choices, possible: new Set(), signature: true, heimat, label };
|
||||
return _taskCache[ingKey];
|
||||
}
|
||||
// Alle Producer (für Klassifizierung) und EU-relevante separat (für Korrekt-Auswahl).
|
||||
// Eigenkonsum-Riesen (Indien-Bananen, USA-Zitronen etc.) sind zwar echte Produzenten,
|
||||
// landen aber nicht in unseren Supermärkten — also nicht als „Spiel-Slot-Korrekt" ziehen.
|
||||
@@ -1109,8 +1133,13 @@ function loadIngredient(){
|
||||
const task = buildTaskFor(ingKey);
|
||||
current.found=[]; current.wrongHere=0; current.wrongStreak=0; current.attempted=new Set();
|
||||
const two = task && task.correct.length > 1;
|
||||
const frage = two
|
||||
? 'finde die <b>zwei</b> Herkunftsländer aus dieser Auswahl'
|
||||
: (task && task.signature
|
||||
? 'aus welchem Land stammt diese Zutat in <b>diesem Gericht</b>?'
|
||||
: 'aus welchem Land kommt diese Zutat häufig zu uns auf den Markt?');
|
||||
document.getElementById('taskBanner').innerHTML=
|
||||
`🔎 Suche: <b>${ing.nm}</b> – ${two?'finde die <b>zwei</b> Herkunftsländer aus dieser Auswahl':'aus welchem Land kommt diese Zutat häufig zu uns auf den Markt?'}`;
|
||||
`🔎 Suche: <b>${ing.nm}</b> – ${frage}`;
|
||||
document.getElementById('resultCard').className="result-card";
|
||||
drawMarkers(ing); renderIngList();
|
||||
}
|
||||
@@ -1194,9 +1223,18 @@ function producerEconHTML(ingKey, correctKeys) {
|
||||
if (!ing || !ing.producers) return '';
|
||||
const all = Object.entries(ing.producers).filter(([c]) => C[c]);
|
||||
all.sort((a,b) => (b[1].t||0) - (a[1].t||0));
|
||||
const top5 = all.slice(0, 5);
|
||||
let html = '<div class="econ-list"><div class="rlabel">Weltweite Hauptproduzenten</div>';
|
||||
top5.forEach(([c, info]) => {
|
||||
const shown = all.slice(0, 5);
|
||||
// Richtige Antwort(en) immer zeigen — auch wenn das Heimatland kein Top-5-Produzent ist
|
||||
correctKeys.forEach(ck => {
|
||||
if (!shown.some(([c]) => c === ck)) {
|
||||
const row = all.find(([c]) => c === ck);
|
||||
if (row) shown.push(row);
|
||||
}
|
||||
});
|
||||
const sig = _taskCache[ingKey] && _taskCache[ingKey].signature;
|
||||
let html = '<div class="econ-list"><div class="rlabel">' +
|
||||
(sig ? 'Die größten Produzenten – zum Vergleich' : 'Weltweite Hauptproduzenten') + '</div>';
|
||||
shown.forEach(([c, info]) => {
|
||||
const isMatch = correctKeys.includes(c);
|
||||
const cm = C[c];
|
||||
const amount = info.t ? fmtTonnes(info.t) : (info.note || 'kulturell verbreitet');
|
||||
@@ -1207,8 +1245,12 @@ function producerEconHTML(ingKey, correctKeys) {
|
||||
<span class="prod-val">${amount}${share}</span>
|
||||
</div>`;
|
||||
});
|
||||
if (all.length > 5) {
|
||||
html += `<div class="prod-more">+ ${all.length - 5} weitere Länder</div>`;
|
||||
const rest = all.length - shown.length;
|
||||
if (rest > 0) {
|
||||
html += `<div class="prod-more">+ ${rest} weitere Länder</div>`;
|
||||
}
|
||||
if (sig) {
|
||||
html += `<div class="prod-more" style="color:#4a7c4e;font-weight:600">Der größte Produzent ist nicht automatisch die Antwort – hier zählt, woher die Zutat für dieses Gericht kommt.</div>`;
|
||||
}
|
||||
html += '</div>';
|
||||
return html;
|
||||
@@ -1226,6 +1268,19 @@ function explainChoice(ingKey, key, isCorrect){
|
||||
const info = ing && ing.producers && ing.producers[key];
|
||||
const amount = info && info.t ? fmtTonnes(info.t) : '';
|
||||
const animal = isAnimalIng(ingKey);
|
||||
// Signatur-Zutat (Heimat-Regel): Antwort folgt dem Gericht
|
||||
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);
|
||||
if (isCorrect) {
|
||||
return {cls:'ok', badge:'✓', text:`Dieses Gericht kommt aus <b>${heimatN}</b> – ${was} ist hier heimisch und wird vor Ort erzeugt.`};
|
||||
}
|
||||
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.`};
|
||||
}
|
||||
// Nicht-Produzent-Fehlklick → normale „unmöglich"-Logik unten
|
||||
}
|
||||
if (isCorrect){
|
||||
if (info && info.market === 'world-far'){
|
||||
return {cls:'ok', badge:'✓', text:`<b>Welt-Hauptproduzent</b> (${amount}) — kommt aber selten in den AT-Handel.`};
|
||||
@@ -1322,6 +1377,10 @@ function showSolved(ing,pts,bonus){
|
||||
const flags=task.correct.map(k=>C[k].f+' '+C[k].n).join(' & ');
|
||||
card.className="result-card ok show";
|
||||
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>`
|
||||
: '';
|
||||
// Caveats für world-far/off-season Korrekt-Picks (pro Land separat)
|
||||
const caveats = task.correct.map(k => {
|
||||
const info = ing.producers && ing.producers[k];
|
||||
@@ -1338,6 +1397,7 @@ function showSolved(ing,pts,bonus){
|
||||
</div>`;
|
||||
}).filter(Boolean).join('');
|
||||
card.innerHTML=`<div class="rc-head">✓ Geschafft! ${esc(ing.nm)} kommt aus: ${flags}</div>
|
||||
${sigLine}
|
||||
${allChoicesHTML(ingKey, task, current.attempted)}
|
||||
${producerEconHTML(ingKey, task.correct)}
|
||||
${caveats}
|
||||
@@ -1362,6 +1422,18 @@ function showWrong(key, kind, ingKey){
|
||||
const c=C[key],card=document.getElementById('resultCard');
|
||||
const ing = ING[ingKey];
|
||||
let head, note;
|
||||
// Signatur-Zutat: „Warum nicht Deutschland?" sofort beantworten
|
||||
const sTask = _taskCache[ingKey];
|
||||
if (sTask && sTask.signature && ing.producers && ing.producers[key]) {
|
||||
card.className="result-card mid show";
|
||||
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>`+
|
||||
`<div class="note">${c.info}<br><br>🔎 Tipp: Achte auf den Namen des Gerichts – er verrät oft die Herkunft.</div>`;
|
||||
return;
|
||||
}
|
||||
if (kind === 'producer-eu-elsewhere') {
|
||||
card.className="result-card mid show";
|
||||
const info = ing.producers[key];
|
||||
|
||||
Reference in New Issue
Block a user