Klima: Flut-Bewertung ans 40%-Spielziel angeglichen

Flut-Score (End- + Live-Score in game-2d/3d) = max(0, 25*(1-Flut/50)): 0% volle 25 Pkt,
40% noch ~5 Pkt, erst ~50% gegen 0 (statt 0 schon ab 31%). Lehrer-Geflutet-Ampel gruen
<25 / gelb <=40 / rot >40. Klima-Stimmung nutzt jetzt den (fairen) Score.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 12:19:41 +02:00
parent c9eb0e7764
commit 5d79fa3c3a
3 changed files with 16 additions and 6 deletions
+2 -2
View File
@@ -1341,7 +1341,7 @@ function _liveKlimaScore() {
if (state.phase !== 'playing' && state.phase !== 'citizen' && state.phase !== 'end') return null;
var sp = state.diff.startPopulation || 6000;
var tempScore = Math.max(0, Math.min(35, 35 - ((state.currentTemp||0) - 15.5) * 20));
var floodScore = Math.max(0, 25 - (state.floodedPct||0) * 0.8);
var floodScore = Math.max(0, 25 * (1 - (state.floodedPct||0) / 50)); // Ziel < 40 %: bei 40 % noch ~5 Pkt
var budgetScore = Math.max(0, Math.min(20, (state.budget||0) / 10));
var popScore = Math.max(0, Math.min(20, ((state.population||0) / sp) * 20));
return Math.round(tempScore + floodScore + budgetScore + popScore);
@@ -3921,7 +3921,7 @@ function computeStars() {
}
function computeScore() {
const tempScore = Math.max(0, Math.min(35, 35 - (state.currentTemp - 15.5) * 20));
const floodScore = Math.max(0, 25 - state.floodedPct * 0.8);
const floodScore = Math.max(0, 25 * (1 - state.floodedPct / 50)); // Ziel < 40 %: bei 40 % noch ~5 Pkt
const budgetScore = Math.max(0, Math.min(20, state.budget / 10));
const popScore = Math.max(0, Math.min(20, (state.population / state.diff.startPopulation) * 20));
return Math.round(tempScore + floodScore + budgetScore + popScore);
+2 -2
View File
@@ -1581,7 +1581,7 @@ function _liveKlimaScore() {
if (state.phase !== 'playing' && state.phase !== 'citizen' && state.phase !== 'end') return null;
var sp = state.diff.startPopulation || 6000;
var tempScore = Math.max(0, Math.min(35, 35 - ((state.currentTemp||0) - 15.5) * 20));
var floodScore = Math.max(0, 25 - (state.floodedPct||0) * 0.8);
var floodScore = Math.max(0, 25 * (1 - (state.floodedPct||0) / 50)); // Ziel < 40 %: bei 40 % noch ~5 Pkt
var budgetScore = Math.max(0, Math.min(20, (state.budget||0) / 10));
var popScore = Math.max(0, Math.min(20, ((state.population||0) / sp) * 20));
return Math.round(tempScore + floodScore + budgetScore + popScore);
@@ -5391,7 +5391,7 @@ function computeStars() {
}
function computeScore() {
const tempScore = Math.max(0, Math.min(35, 35 - (state.currentTemp - 15.5) * 20));
const floodScore = Math.max(0, 25 - state.floodedPct * 0.8);
const floodScore = Math.max(0, 25 * (1 - state.floodedPct / 50)); // Ziel < 40 %: bei 40 % noch ~5 Pkt
const budgetScore = Math.max(0, Math.min(20, state.budget / 10));
const popScore = Math.max(0, Math.min(20, (state.population / state.diff.startPopulation) * 20));
return Math.round(tempScore + floodScore + budgetScore + popScore);
+12 -2
View File
@@ -737,7 +737,15 @@ var LIVE_PRIMARY_FIELDS = {
// Kennzahlen mit Ampel-Linien (grün→rot), absolute Skalen wie im Spiel:
{k:'co2', label:'CO₂', unit:'ppm', fmt:function(v){ return _liveBar(v, 280, 700, 'low'); }},
{k:'temp', label:'Temp', unit:'°C', fmt:function(v){ return _liveBar(v, 14, 20, 'low', 1); }},
{k:'floodedPct', label:'Geflutet', unit:'%', fmt:function(v){ return _liveBar(v, 0, 100, 'low'); }},
{k:'floodedPct', label:'Geflutet', unit:'%', fmt:function(v){
// Ampel am Spielziel „Stadt schützen < 40 %": grün < 25, gelb 2540, rot > 40.
if (v==null||isNaN(v)) return '<span style="color:#9a9a9a"></span>';
var c = v < 25 ? '#5a8a5e' : v <= 40 ? '#c9913a' : '#c07a6b';
var pct = Math.max(0, Math.min(100, v));
return '<span style="display:inline-flex;align-items:center;gap:.35rem;font-variant-numeric:tabular-nums">'
+ '<span aria-hidden="true" style="display:inline-block;width:42px;height:7px;border-radius:99px;background:rgba(0,0,0,.08);overflow:hidden"><span style="display:block;height:100%;width:'+pct.toFixed(0)+'%;background:'+c+'"></span></span>'
+ '<span style="color:'+c+';font-weight:700;font-size:.8rem;min-width:1.6em;text-align:right">'+Math.round(v)+'</span></span>';
}},
{k:'budget', label:'Budget', unit:'Mio €', fmt:function(v){ return _liveBar(v, -500, 3000, 'high'); }},
{k:'population', label:'Bev.', fmt:function(v, row){
// Relativ zur Startbevölkerung (Level 3 = 7000, sonst 6000): unter Start = rot,
@@ -1292,7 +1300,9 @@ function _liveMood(simId, s) {
switch (simId) {
case 'weltkueche': return (s.mistakesInDish||0) <= 2 ? 'good' : (s.mistakesInDish >= 8 ? 'bad' : 'mid');
case 'farmer': return (s.hit_rate==null) ? 'mid' : (s.hit_rate >= 60 ? 'good' : s.hit_rate >= 30 ? 'mid' : 'bad');
case 'klima': case 'klima-3d': return ((s.floodedPct==null?100:s.floodedPct) < 20 && (s.budget||0) >= 0) ? 'good' : 'mid';
case 'klima': case 'klima-3d': return (typeof s.score === 'number')
? (s.score >= 65 ? 'good' : s.score >= 40 ? 'mid' : 'bad')
: (((s.floodedPct==null?100:s.floodedPct) < 25 && (s.budget||0) >= 0) ? 'good' : 'mid');
case 'busfahrt': case 'fluggesellschaft': return (s.budget==null?0:s.budget) >= 5000 ? 'good' : (s.budget < 0 ? 'bad' : 'mid');
case 'tourismustal': return (s.money==null?0:s.money) >= 4000 ? 'good' : (s.money < 0 ? 'bad' : 'mid');
case 'heli': return (s.totalStars||0) >= 4 ? 'good' : 'mid';