Tourismustal: Komplett-Integration (Sim + Wrapper + SQL + Lehrer-Backend)

Sim nach App/sims/tourismustal umgezogen (Source of Truth), game.html mit
Injection-Marker. Neu in der Sim: 5 Sommergebaeude (Bikepark mit Flowtrails,
Hochseilgarten, Fahrradverleih als Verstaerker, Aussichtsplattform,
Erlebnisspielplatz), Rettungsstation mit Notarzthubschrauber, Ausbau-
Bauanimation, Event-Pacing, Schulden-Notbremse (Bank-Zwangsverkauf),
Berater-Tipps (Ruecklagen), Sommer-Trend-Mechanik (Serfaus-Effekt) und
Wissens-Bausteine mit echten DACH-Tourismusdaten (QUELLEN.md).

Plattform: PHP-Wrapper mit base-Tag + Session-Mode, Modul-Detailseite,
module_info (beta) + Glossar (14 Begriffe inkl. Leichter Sprache + Quellen)
+ Lehrplan-Anker AT/DE/CH an neuer Kompetenz tourismus-raumentwicklung.
Lehrer-Backend: Benchmark-Formel, Live-Cockpit-Spalten, needsHelp-Heuristik,
Modul-Highlights. Strategie-Testharness (tests/strategien.mjs) belegt:
Panzer-Rush wird liquidiert, Ruecklagen zahlen sich aus.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-11 02:45:08 +02:00
parent eb565d4c01
commit 0a2ebf46b4
55 changed files with 6820 additions and 0 deletions
+2
View File
@@ -621,6 +621,8 @@ if ($method === 'GET') {
return ($state['balance'] ?? 1000) < 0;
case 'eu-werkstatt':
return ($state['attemptsThisStep'] ?? 0) >= 6;
case 'tourismustal':
return ($state['money'] ?? 1) < 0 || ($state['lossStreak'] ?? 0) >= 8;
}
return false;
};
+7
View File
@@ -74,6 +74,13 @@ $MODULE_HIGHLIGHTS = [
['key'=>'routes_completed','label'=>'Routen', 'agg'=>'max'],
['key'=>'avg_accuracy', 'label'=>'Genauigkeit','agg'=>'max','format'=>'percent'],
],
'tourismustal' => [
['key'=>'results.money', 'label'=>'Konto', 'agg'=>'max', 'unit'=>'€'],
['key'=>'results.maxGuests', 'label'=>'Gäste-Rekord','agg'=>'max'],
['key'=>'results.maxSummerGuests', 'label'=>'Sommer-Rekord','agg'=>'max'],
['key'=>'results.nature', 'label'=>'Naturwert', 'agg'=>'max', 'unit'=>'%'],
['key'=>'results.goalsDone', 'label'=>'Ziele', 'agg'=>'max'],
],
];
// Hilfsfunktion: holt einen Wert aus einem JSON-Pfad ("results.money" → $json['results']['money']).
+22
View File
@@ -52,6 +52,7 @@ class Benchmark
'fluss' => self::scoreFluss($results),
'fluggesellschaft' => self::scoreFluggesellschaft($results),
'kofferdetektiv' => self::scoreKofferdetektiv($results),
'tourismustal' => self::scoreTourismustal($results),
// Entscheidungstag: kein assessment-Submit-Pfad bekannt → null
default => self::scoreFallbackStars($results),
};
@@ -437,6 +438,27 @@ class Benchmark
return (int)round(max(0, min(100, $base + $clean + $sparse - $malus)));
}
/**
* Tourismustal — Zielerreichung × Zufriedenheit × Naturwert Schulden-Malus.
* 50 % Szenen-Ziele + 25 % Gäste-Zufriedenheit + 25 % Naturwert,
* 15 wenn das Konto im Minus endet (Rücklagen sind Teil der Didaktik).
* Felder aus dem Submit-Hook (game.html → progress.php submit_assessment).
*/
private static function scoreTourismustal(array $r): ?int
{
$goalsDone = $r['goalsDone'] ?? null;
$goalsTotal = (int)($r['goalsTotal'] ?? 0);
if (!is_numeric($goalsDone) || $goalsTotal <= 0) return null;
$sat = (float)($r['satisfaction'] ?? 0);
$nature = (float)($r['nature'] ?? 0);
$money = (float)($r['money'] ?? 0);
$score = ($goalsDone / $goalsTotal) * 50
+ ($sat / 100) * 25
+ ($nature / 100) * 25
- ($money < 0 ? 15 : 0);
return (int)round(max(0, min(100, $score)));
}
/**
* Generischer Fallback: Sterne aus 5-er-Skala.
*/