Modul-Klassenuebersicht: Ampelbalken pro Zelle + Verlauf als Liniengrafik

- renderModDetail: kleiner Ampelbalken je Kennzahl-Zelle, Werte spaltenweise
  normiert, Richtung aus h.agg (gruen=positiv, weniger-ist-besser invertiert)
- Sterne-Zelle mit Ampelbalken (n/5)
- Verlauf-Button zeigt statt JSON eine Liniengrafik ueber die wichtigsten
  Kennzahlen (eine Linie je Highlight-Spalte + Sterne, oben=besser, Legende
  mit letztem Wert + Trendpfeil); Snapshot-Kacheln bei nur einem Durchgang
- sim-metrics.js: dir:'lo' fuer Kennzahlen wo weniger besser ist

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 16:00:44 +02:00
parent 5bf8f0fe03
commit d1a01915af
2 changed files with 169 additions and 12 deletions
+28 -9
View File
@@ -19,7 +19,7 @@
{k:'stars',type:'stars',l:'Sterne'},
{k:'final_temperature',type:'temp',l:'Temperatur'},
{k:'final_flooded_pct',type:'pctInv',l:'Überflutung'},
{k:'final_co2',type:'num',l:'CO₂',u:'ppm'},
{k:'final_co2',type:'num',l:'CO₂',u:'ppm',dir:'lo'},
{k:'final_budget',type:'money',l:'Budget'},
{k:'final_population',type:'num',l:'Bevölkerung'},
{k:'measures_bought',type:'num',l:'Maßnahmen'}
@@ -37,7 +37,7 @@
{k:'stars',type:'stars',l:'Sterne'},
{k:'wonOrders',type:'ratio',t:'totalOrders',l:'Aufträge gewonnen'},
{k:'quizFirstTry',type:'ratio',t:'totalOrders',l:'Quiz Erstversuch'},
{k:'avgTapKm',type:'num',l:'Ø Abweichung',u:'km'}
{k:'avgTapKm',type:'num',l:'Ø Abweichung',u:'km',dir:'lo'}
],
farmer: [
{k:'stars',type:'stars',l:'Sterne'},
@@ -51,7 +51,7 @@
],
'eu-werkstatt': [
{k:'firstTryHits',type:'ratio',t:'stepsTotal',l:'Erste Wahl'},
{k:'muelleimerCount',type:'num',l:'verworfen'},
{k:'muelleimerCount',type:'num',l:'verworfen',dir:'lo'},
{k:'endType',type:'text',l:'Ergebnis'}
],
energiemanager: [
@@ -62,7 +62,7 @@
weltkueche: [
{k:'stars',type:'stars',l:'Sterne'},
{k:'completedDishes',type:'ratio',t:'totalDishes',l:'Gerichte'},
{k:'mistakesInDish',type:'num',l:'Fehlklicks'},
{k:'mistakesInDish',type:'num',l:'Fehlklicks',dir:'lo'},
{k:'dishName',type:'text',l:'Aktuelles Gericht'},
{k:'ingSolved',type:'ratio',t:'ingTotal',l:'Zutaten gelöst'},
{k:'progressPct',type:'pct',l:'Fortschritt'}
@@ -70,7 +70,7 @@
logistik: [
{k:'stars',type:'stars',l:'Sterne'},
{k:'ordersDelivered',type:'ratio',t:'totalOrders',l:'Ausgeliefert'},
{k:'ordersLate',type:'num',l:'verspätet'},
{k:'ordersLate',type:'num',l:'verspätet',dir:'lo'},
{k:'finalBalance',type:'money',l:'Bilanz'},
{k:'balance',type:'money',l:'Konto'}
],
@@ -84,7 +84,7 @@
kofferdetektiv: [
{k:'cases_solved',type:'ratio',t:'cases_total',l:'Fälle gelöst'},
{k:'correct_first_try',type:'num',l:'Erstversuch'},
{k:'wrong_guesses',type:'num',l:'Fehlversuche'}
{k:'wrong_guesses',type:'num',l:'Fehlversuche',dir:'lo'}
],
tourismustal: [
{k:'goalsDone',type:'ratio',t:'goalsTotal',l:'Ziele erreicht'},
@@ -158,7 +158,26 @@
: '<span style="font-size:.72rem;color:#8a8a8a">keine auswertbaren Parameter</span>';
}
root.SIM_METRICS = SIM_METRICS;
root.renderSimMetrics = renderSimMetrics;
root.ggsStarsHtml = stars;
// Plottbare (numerische) Kennzahlen einer Sim, dedupliziert nach Label.
var PLOTTABLE = {stars:1, starsSmall:1, pct:1, pctInv:1, ratio:1, temp:1, money:1, num:1};
function simPlotMetrics(simId){
var seen = {}, out = [];
(SIM_METRICS[simId] || []).forEach(function(f){
if (!PLOTTABLE[f.type] || seen[f.l]) return;
seen[f.l] = 1; out.push(f);
});
return out;
}
// true = höher ist besser (grün oben). temp/pctInv und dir:'lo' → niedriger ist besser.
function metricHigherBetter(f){
if (f.dir === 'lo') return false;
if (f.dir === 'hi') return true;
return !(f.type === 'pctInv' || f.type === 'temp');
}
root.SIM_METRICS = SIM_METRICS;
root.renderSimMetrics = renderSimMetrics;
root.ggsStarsHtml = stars;
root.simPlotMetrics = simPlotMetrics;
root.metricHigherBetter = metricHigherBetter;
})(typeof window !== 'undefined' ? window : this);