From 13f14c26a8bc95469fb890b1d04772f5a2798706 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 22 Aug 2026 00:35:24 +0200 Subject: [PATCH] Weltkueche: 6 Zutaten mit fest verdrahteter Herkunft (Thomas-Vorgaben) Kein Automatismus mehr - Zutat hat feste Laenderliste (correct) + feste Distraktoren, die das Spiel 1:1 ausliest. Vorrang vor Consumer/Heimat. - greyerzer (NEU, "Greyerzer & Vacherin"): Schweiz+Frankreich -> ersetzt den mozzarella-Hack im Fondue (Signatur entfernt, Rezept nannte Gruyere+Vacherin schon korrekt). - hefe: Oesterreich+Frankreich | lamm: Neuseeland+UK (Import, nicht Griechenland) tomaten: Niederlande+Spanien | schmand: Oesterreich+Deutschland fischsauce: Thailand+Vietnam (nicht Italien). game.html: schlanker Auslese-Zweig fuer `correct`/`distractors` (isWorldIngredient + ING-Build + Aufloesungstext). admin spiegelt als "Feste Herkunft". Co-Authored-By: Claude Opus 4.8 --- App/admin-weltkueche.html | 8 +- App/sims/weltkueche/assets/data/dishes.json | 6 +- .../assets/data/production-matrix.json | 84 +++++++++++++++++++ App/sims/weltkueche/game.html | 25 +++++- 4 files changed, 116 insertions(+), 7 deletions(-) diff --git a/App/admin-weltkueche.html b/App/admin-weltkueche.html index 221a965..2fb6063 100644 --- a/App/admin-weltkueche.html +++ b/App/admin-weltkueche.html @@ -99,6 +99,12 @@ function classify(ingKey, heimat, isSig){ var ing = PM[ingKey]; if (!ing) return null; var producers = ing.producers || {}; var keys = Object.keys(producers).filter(function(c){ return C[c]; }); + // ── FEST VERDRAHTETE HERKUNFT: feste Länderliste + feste Distraktoren. + if (ing.correct && ing.correct.length) { + var fc = ing.correct.filter(function(c){ return C[c]; }); + var fd = (ing.distractors||[]).filter(function(c){ return C[c] && fc.indexOf(c)<0; }); + return { correct: fc, distractors: fd, branch:'fest', grav:function(){return 0;} }; + } // ── CONSUMER-REGEL (Teil B): Grundzutat, im Land des Users heimisch → kommt aus // dem Land des Users (unabhängig vom Gericht-Land). Signaturzutaten ausgenommen. if (!isSig && ing.heimisch && ing.heimisch.indexOf(WK_USER) >= 0 && C[WK_USER]) { @@ -175,7 +181,7 @@ function render(){ if (onlyWarn && !warn) return; var okChips = cl.correct.map(function(c){ return ctyChip(c,'ok',k,heimat,true); }).join(''); var distChips = cl.distractors.slice(0,6).map(function(c){ return ctyChip(c,'dist',k,heimat,false); }).join(''); - rows += ''+(PM[k].ic||'')+' '+(PM[k].nm||k)+''+(cl.branch==='consumer'?'🛒 Consumer-Regel (User-Land)':(cl.branch==='heimat'?'Heimat-Regel':'Welt-Zutat'))+'' + rows += ''+(PM[k].ic||'')+' '+(PM[k].nm||k)+''+(cl.branch==='fest'?'📌 Feste Herkunft':(cl.branch==='consumer'?'🛒 Consumer-Regel (User-Land)':(cl.branch==='heimat'?'Heimat-Regel':'Welt-Zutat')))+'' + '
richtig
'+(okChips||'—')+warn+'' + '
Distraktoren (Pool)
'+(distChips||'—')+''; }); diff --git a/App/sims/weltkueche/assets/data/dishes.json b/App/sims/weltkueche/assets/data/dishes.json index ce9629f..cb7c03b 100644 --- a/App/sims/weltkueche/assets/data/dishes.json +++ b/App/sims/weltkueche/assets/data/dishes.json @@ -780,7 +780,7 @@ "pfeffer", "muskat", "knoblauch", - "mozzarella" + "greyerzer" ], "pantry": [], "recipe": { @@ -817,9 +817,7 @@ "diff_note": "Käse-Verhältnis + Achter-Rührtechnik (nie Kreis) — Detail entscheidet", "id": "schweizer-kaesefondue", "heimat": "schweiz", - "signature": { - "mozzarella": "Schweizer Bergkäse" - } + "signature": {} }, "zuercher-geschnetzeltes": { "name": "Zürcher Geschnetzeltes mit Rösti", diff --git a/App/sims/weltkueche/assets/data/production-matrix.json b/App/sims/weltkueche/assets/data/production-matrix.json index ec66767..2d6394f 100644 --- a/App/sims/weltkueche/assets/data/production-matrix.json +++ b/App/sims/weltkueche/assets/data/production-matrix.json @@ -2856,6 +2856,35 @@ ], "fact": "Irische Butter ist oft gelber als deutsche — weil die Kühe das ganze Jahr auf der Weide stehen und mehr Beta-Carotin aufnehmen." }, + "greyerzer": { + "nm": "Greyerzer & Vacherin", + "art": "der", + "ic": "🧀", + "producers": { + "schweiz": { + "t": 32000, + "market": "eu", + "note": "Gruyère AOP + Vacherin Fribourgeois AOP" + }, + "frankreich": { + "t": 6000, + "market": "eu", + "note": "Gruyère français IGP" + } + }, + "correct": [ + "schweiz", + "frankreich" + ], + "distractors": [ + "deutschland", + "oesterreich", + "italien", + "niederlande", + "daenemark" + ], + "fact": "Echtes Käsefondue ist ‚Moitié-Moitié’ — halb Greyerzer (Gruyère AOP), halb Vacherin Fribourgeois AOP. Beide sind Schweizer Bergkäse mit geschützter Herkunft; Gruyère wird auch im französischen Jura hergestellt (IGP)." + }, "feta": { "nm": "Feta (Käse)", "art": "der", @@ -3040,6 +3069,17 @@ "fact": "Aus 5 L Milch wird etwa 1 kg Topfen. Wichtige Eiweißquelle für Sportler:innen." }, "schmand": { + "correct": [ + "oesterreich", + "deutschland" + ], + "distractors": [ + "polen", + "tschechien", + "niederlande", + "frankreich", + "daenemark" + ], "nm": "Schmand / Saure Sahne", "art": "der", "ic": "🥛", @@ -3171,6 +3211,17 @@ "fact": "Bei einem traditionellen Wiener Schnitzel kommt das Kalbfleisch fast immer aus dem nahen Umfeld (AT, DE, NL)." }, "lamm": { + "correct": [ + "neuseeland", + "uk" + ], + "distractors": [ + "griechenland", + "tuerkei", + "frankreich", + "spanien", + "deutschland" + ], "nm": "Lammfleisch", "art": "das", "ic": "🐑", @@ -3583,6 +3634,17 @@ ] }, "fischsauce": { + "correct": [ + "thailand", + "vietnam" + ], + "distractors": [ + "philippinen", + "italien", + "china", + "japan", + "indien" + ], "nm": "Fischsauce", "art": "die", "ic": "🐟", @@ -3730,6 +3792,17 @@ "fact": "Echter Wasabi ist extrem selten und teuer — in den meisten Sushi-Restaurants wird Meerrettich mit grüner Farbe als Ersatz verwendet." }, "tomaten": { + "correct": [ + "niederlande", + "spanien" + ], + "distractors": [ + "griechenland", + "italien", + "tuerkei", + "marokko", + "aegypten" + ], "nm": "Tomaten", "art": "die", "ic": "🍅", @@ -4371,6 +4444,17 @@ "fact": "Champignons brauchen kein Tageslicht — sie wachsen in dunklen Hallen auf Stroh-Mist-Kompost." }, "hefe": { + "correct": [ + "oesterreich", + "frankreich" + ], + "distractors": [ + "italien", + "spanien", + "griechenland", + "polen", + "tuerkei" + ], "nm": "Hefe", "art": "die", "ic": "🫧", diff --git a/App/sims/weltkueche/game.html b/App/sims/weltkueche/game.html index 398b506..5fd7aad 100644 --- a/App/sims/weltkueche/game.html +++ b/App/sims/weltkueche/game.html @@ -538,7 +538,8 @@ async function loadWeltkuecheData() { more: v.more || '', heimisch: v.heimisch || null, // Teil B: Länder mit Eigenanteil ≥ ⅓ (Consumer-Anker) market: v.market || null, // Teil B: kuratierte Markt-Zweitlieferanten - distractors: v.distractors || null // Teil B: explizite Distraktor-Länder + distractors: v.distractors || null, // explizite Distraktor-Länder + correct: v.correct || null // fest verdrahtete Herkunft (feste Länderliste) }; }); DISHES = Object.entries(dishesJ) @@ -979,6 +980,7 @@ function worldIngCount(dish){ * wird im Game als "lokal verfügbar" angezeigt, aber nicht erforscht. */ function isWorldIngredient(key) { const ing = ING[key]; if (!ing) return false; + if (ing.correct && ing.correct.length) return true; // fest verdrahtete Herkunft: wird abgefragt if (ing.heimisch && ing.heimisch.length) return true; // Consumer-Grundzutat (Teil B): wird immer abgefragt const real = Object.values(ing.producers || {}).filter(p => p.t && p.t > 0); return real.length >= 3; @@ -1068,6 +1070,22 @@ function buildTaskFor(ingKey) { if (_taskCache[ingKey]) return _taskCache[ingKey]; const ing = ING[ingKey]; if (!ing) return null; + // ── FEST VERDRAHTETE HERKUNFT: Zutat hat eine feste Länderliste (`correct`) + // + feste Distraktoren (`distractors`). Gilt immer — kein Automatismus, + // einfach genau die vorgegebene Liste. Hat Vorrang vor allem anderen. + if (ing.correct && ing.correct.length) { + const correct = ing.correct.filter(c => C[c]); + let pool = (ing.distractors || []).filter(c => C[c] && !correct.includes(c)); + if (pool.length < 5 - correct.length) { + pool = pool.concat(impossibleCountries(correct, [...pool, ...Object.keys(ing.producers || {})])); + } + shuffleInPlace(pool); + const distr = pool.slice(0, Math.max(0, 5 - correct.length)); + const choices = [...correct, ...distr]; + shuffleInPlace(choices); + _taskCache[ingKey] = { correct, choices, possible: new Set(), fixed: true }; + return _taskCache[ingKey]; + } // ── CONSUMER-REGEL (Teil B): Eine Grundzutat, die im Land des USERS heimisch // ist (Eigenanteil ≥ ~⅓), kauft man dort, wo man einkauft — im eigenen Land, // UNABHÄNGIG davon, aus welchem Land das Gericht stammt. (Das Ei in der @@ -1588,7 +1606,10 @@ function showSolved(ing,pts,bonus){ const factLine = ing.fact ? `
Wusstest du? ${esc(ing.fact)}
` : ''; // Heimat-Regel: erklären, warum die Region die Antwort ist (nicht der größte Produzent) const _userN = task.user && C[task.user] ? (C[task.user].f + ' ' + C[task.user].n) : 'bei uns'; - const sigLine = task.consumer + const _fixN = task.fixed ? task.correct.map(k => C[k] ? (C[k].f + ' ' + C[k].n) : k).join(' & ') : ''; + const sigLine = task.fixed + ? `
🌍 ${esc(ing.nm)} kommt bei uns typisch aus ${_fixN}.
` + : task.consumer ? `
🛒 Eine Grundzutat — die kaufst du dort, wo du einkaufst: im eigenen Land (${_userN}). Reicht die heimische Menge nicht, kommt ein naher Nachbar dazu. Nur was bei uns gar nicht wächst, reist von weit her — und was ein Gericht besonders macht, holt man aus der Herkunftsregion.
` : (task.signature && C[task.heimat]) ? (task.label