Weltkueche Teil B: Consumer-Anker (Herkunft folgt dem User-Land) — Pilot Ei/Kartoffel/Semmelbroesel

Grundzutaten, die im Land des Users heimisch sind, kommen jetzt aus dem Land
des USERS statt aus dem Gericht-Land (Carbonara-Ei in AT = AT-Ei). Opt-in pro
Zutat ueber neues Feld `heimisch`; Signaturzutaten bleiben am Gericht.

game.html:
- buildTaskFor: neuer Consumer-Zweig (vor Heimat-Regel). correct = [User-Land,
  ...market], Distraktoren explizit (`distractors`) oder berechnet. Immer 5 Karten.
- _wkUser(): WK_COUNTRY (AT/DE/CH/LI) -> Laender-Slug, Fallback AT.
- isWorldIngredient: Zutat mit `heimisch` wird immer abgefragt (z.B. Semmelbroesel).
- ING-Build: heimisch/market/distractors werden aus der Matrix mitkopiert
  (wurden vorher weggelassen -> Felder kamen nie im Spiel an).
- Aufloesungstext: Consumer-Fall ("kaufst du, wo du einkaufst - im eigenen Land").

Daten (production-matrix.json), Thomas-Vorgaben:
- eier:  heimisch AT/DE/CH, market DE+NL  -> AT-User: AT+DE+NL, DE-User: DE+NL
- kartoffel: heimisch AT/DE/CH, market DE -> AT+DE (alle Gerichte)
- semmelbroesel: heimisch AT/DE, market DE, distractors GR/TR/EG/TN/IE; jetzt abgefragt

admin-weltkueche.html: Consumer-Zweig gespiegelt + AT/DE/CH-Umschalter.

Nebenbefund (NICHT angefasst): correct_for wird im Spiel nie gelesen (nur Admin
las es) -> mehl/majoran/safran/feta-lamm-Kuratierung wirkte bisher nur im Admin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-21 18:21:39 +02:00
parent b6b6c6ccce
commit 423490260d
3 changed files with 112 additions and 16 deletions
+23 -3
View File
@@ -65,6 +65,12 @@
<span class="chip" data-cat="europa" onclick="setCat(this,'europa')">Europa</span>
<span class="chip" data-cat="exotisch" onclick="setCat(this,'exotisch')">Exotisch</span>
<label style="font-size:.72rem;color:#6a6a6a;margin-left:.5rem"><input type="checkbox" id="onlyWarn" onchange="render()"> nur Auffällige ⚠</label>
<label style="font-size:.72rem;color:#6a6a6a;margin-left:.5rem">🛒 Land des Users:
<select id="userCty" onchange="setUser(this.value)" style="font-size:.72rem;padding:.15rem .3rem">
<option value="oesterreich">🇦🇹 Österreich</option>
<option value="deutschland">🇩🇪 Deutschland</option>
<option value="schweiz">🇨🇭 Schweiz</option>
</select></label>
</div>
<div id="status">Lade Daten…</div>
<div id="list"></div>
@@ -74,6 +80,8 @@ var BASE = location.pathname.replace(/\/admin-weltkueche\.html$/, '');
var D = 'sims/weltkueche/assets/data/';
var C = {}, PM = {}, DISHES = [];
var _cat = '';
var WK_USER = 'oesterreich'; // Teil B: Land des Users (Consumer-Anker) — via Umschalter
function setUser(v){ WK_USER = v || 'oesterreich'; render(); }
// ---- Spiel-Logik gespiegelt (siehe game.html buildTaskFor) ----
function mrank(m){ return m === 'eu' ? 0 : (m === 'world-far' || m === 'local') ? 2 : 1; }
@@ -87,10 +95,22 @@ function wkDist(a, b){
}
// Klassifiziert alle Produzenten einer Zutat für ein Gericht.
// Gibt { correct:[keys], distractors:[keys], branch } zurück (Pools, ohne Zufalls-Ziehung).
function classify(ingKey, heimat){
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]; });
// ── 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]) {
var cmarket = (ing.market||[]).filter(function(c){ return C[c] && c !== WK_USER; });
var ccorrect = [WK_USER].concat(cmarket).slice(0,3);
if (ccorrect.length < 2){ for (var hi=0; hi<(ing.heimisch||[]).length; hi++){ var hh=ing.heimisch[hi]; if(C[hh]&&ccorrect.indexOf(hh)<0){ccorrect.push(hh);break;} } }
var cdistr;
if (ing.distractors && ing.distractors.length){ cdistr = ing.distractors.filter(function(c){ return C[c] && ccorrect.indexOf(c)<0; }); }
else { var cfar = keys.filter(function(c){ var mm=producers[c].market; return (mm==='world-far'||mm==='local') && ccorrect.indexOf(c)<0; }).sort(function(a,b){ return (producers[b].t||0)-(producers[a].t||0); });
var cclim = (ing.climate_possible||[]).filter(function(c){ return C[c] && ccorrect.indexOf(c)<0; }); cdistr = cfar.concat(cclim); }
return { correct: ccorrect, distractors: cdistr, branch:'consumer', grav:function(){return 0;} };
}
// Heimat-Zweig: Heimat erzeugt die Zutat selbst
if (heimat && C[heimat] && producers[heimat]) {
var grav = function(c){ return (producers[c].t || 0) / wkDist(heimat, c); };
@@ -143,7 +163,7 @@ function render(){
var rows = ''; var dishHasWarn = false;
ings.forEach(function(k){
if (q && (d.name||'').toLowerCase().indexOf(q)<0 && (PM[k].nm||k).toLowerCase().indexOf(q)<0) return;
var cl = classify(k, heimat); if(!cl) return;
var cl = classify(k, heimat, !!(d.signature && d.signature[k])); if(!cl) return;
// Auffällig NUR im Heimat-Zweig: die Zutat ist lokal erzeugbar (Heimat baut
// sie an), trotzdem ist ein „richtiges" Land > 1500 km weg → echter Ausreißer.
// Welt-Zutaten (Pfeffer aus Vietnam etc.) sind zu Recht fern → keine Warnung.
@@ -155,7 +175,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 += '<tr><td class="ing-nm">'+(PM[k].ic||'')+' '+(PM[k].nm||k)+'<small>'+(cl.branch==='heimat'?'Heimat-Regel':'Welt-Zutat')+'</small></td>'
rows += '<tr><td class="ing-nm">'+(PM[k].ic||'')+' '+(PM[k].nm||k)+'<small>'+(cl.branch==='consumer'?'🛒 Consumer-Regel (User-Land)':(cl.branch==='heimat'?'Heimat-Regel':'Welt-Zutat'))+'</small></td>'
+ '<td><div class="colhead">richtig</div>'+(okChips||'—')+warn+'</td>'
+ '<td><div class="colhead">Distraktoren (Pool)</div>'+(distChips||'—')+'</td></tr>';
});