diff --git a/App/sims/weltkueche/game.html b/App/sims/weltkueche/game.html index bd130bb..f4d7910 100644 --- a/App/sims/weltkueche/game.html +++ b/App/sims/weltkueche/game.html @@ -1031,6 +1031,17 @@ function ingWas(ing, sTask, ingKey) { return a + ' ' + (ing ? ing.nm : ''); } +// Entfernung zweier Länder (Haversine, km) über die Länder-Koordinaten. +// Für die Handels-Gravitation (Menge ÷ Entfernung) beim Zweit-Lieferanten. +function _wkDist(a, b) { + const A = C[a], B = C[b]; + if (!A || !B || A.lat == null || B.lat == null) return 3000; + const R = 6371, toR = Math.PI / 180; + const dLat = (B.lat - A.lat) * toR, dLng = (B.lng - A.lng) * toR; + const s = Math.sin(dLat / 2) ** 2 + Math.cos(A.lat * toR) * Math.cos(B.lat * toR) * Math.sin(dLng / 2) ** 2; + return Math.max(60, 2 * R * Math.asin(Math.min(1, Math.sqrt(s)))); +} + function buildTaskFor(ingKey) { if (_taskCache[ingKey]) return _taskCache[ingKey]; const ing = ING[ingKey]; @@ -1054,9 +1065,14 @@ function buildTaskFor(ingKey) { // (global/ungetaggt). „world-far"/„local" (wächst dort, landet aber nicht in unseren // Regalen) zählen NICHT als korrekt. const mrank = m => (m === 'eu' ? 0 : (m === 'world-far' || m === 'local') ? 2 : 1); + // Zweit-Lieferant = realistisch für UNSEREN Markt via Handels-Gravitation: + // Menge ÷ Entfernung zur Heimat. Ein naher großer Nachbar schlägt einen + // fernen Großproduzenten (AT-Eier → Deutschland, NICHT Frankreich), obwohl + // Frankreich mehr Eier erzeugt. Markt-Tier bleibt vorrangig (EU vor global). + const grav = ([c, info]) => (info.t || 0) / _wkDist(heimat, c); const realistic = Object.entries(ing.producers) .filter(([c, info]) => C[c] && c !== heimat && mrank(info.market) < 2) - .sort((a, b) => (mrank(a[1].market) - mrank(b[1].market)) || ((b[1].t || 0) - (a[1].t || 0))) + .sort((a, b) => (mrank(a[1].market) - mrank(b[1].market)) || (grav(b) - grav(a))) .map(([c]) => c); const correct = [heimat, ...realistic.slice(0, 1)]; // Heimat + eine realistische Zweit-Wahl (wie normaler Zweig: 2 Korrekte) if (correct.length < 2) { // Garantie: es gibt IMMER eine zweite Wahl @@ -1231,9 +1247,11 @@ function loadIngredient(){ : (task && task.signature ? 'aus welchem Land stammt diese Zutat in diesem Gericht?' : 'aus welchem Land kommt diese Zutat häufig zu uns auf den Markt?'); + const _nd = Math.max(1, task ? (task.choices.length - task.correct.length) : 4); + const _per = Math.round(100 / _nd); document.getElementById('taskBanner').innerHTML= `🔎 Suche: ${ing.nm} – ${frage}` - + ` · richtig +100, jeder Fehlklick −25 (¼)`; + + ` · richtig +100, jeder Fehlklick −${_per} (alle falsch zuerst = 0)`; document.getElementById('resultCard').className="result-card"; drawMarkers(ing); renderIngList(); } @@ -1270,7 +1288,10 @@ function guess(key){ playSfx('click-country'); if (cls === 'correct') { b.classList.add('correct'); - const pts = Math.max(0, 100 - 25 * (current.wrongHere || 0)); // richtig = 100; jeder Fehlklick auf dieser Zutat: −25 (¼) + // Strafe pro Fehlklick so, dass „alle Falschen zuerst" IMMER 0 ergibt: + // 100 ÷ Anzahl Distraktoren. Bei 4 Distraktoren = −25 (¼), bei 2 = −50. + const numDistr = Math.max(1, task ? (task.choices.length - task.correct.length) : 4); + const pts = Math.max(0, Math.round(100 - (100 / numDistr) * (current.wrongHere || 0))); state.score+=pts; current.dishScore+=pts; state.totalCorrect++; current.wrongStreak=0; current.found.push(key); map.flyTo([c.lat,c.lng],3,{duration:.7});