Files
geograsim/App/php/generate-city-panoramas.php
Adminator 1e51ef7def Nachtrag: alle bisher untracked Ordner + hängende Änderungen mit-committen
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/
- 12 code-workspace-Files
- STATUS-*.md
- viele M/D/R-Änderungen an bereits getrackten Files
- .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-08 02:27:02 +02:00

150 lines
8.5 KiB
PHP

<?php
/**
* Stadt-Panorama-Generator fuer Heli-Uebersichtskarte.
* Stil exakt wie Logistik (Flat Scandinavian Illustration), Format
* 1792x1024 (16:9 panoramisch). Pro Stadt eigenes Wahrzeichen.
*
* Aufruf via Browser:
* http://localhost/geograsim/App/php/generate-city-panoramas.php
* ?ids=linz,klagenfurt (nur diese)
* ?force=1 (ueberschreibt vorhandene)
*/
set_time_limit(0);
ignore_user_abort(true);
header('Content-Type: text/plain; charset=utf-8');
$envFile = __DIR__ . '/../.env.local';
if (!file_exists($envFile)) { exit("ERROR: .env.local fehlt\n"); }
$OPENAI_KEY = '';
foreach (file($envFile) as $ln) {
$ln = trim($ln);
if ($ln === '' || $ln[0] === '#') continue;
if (preg_match('/^OPENAI_API_KEY\s*=\s*(.+)$/', $ln, $m)) {
$OPENAI_KEY = trim($m[1], " \t\"'");
break;
}
}
if (!$OPENAI_KEY) { exit("ERROR: OPENAI_API_KEY nicht in .env.local gefunden\n"); }
// ---- Verbindlicher Stil-Vorspann (exakt wie Logistik PROMPT_BASE) ----
$STYLE = "Flat Scandinavian illustration, wide panoramic landscape filling the entire 16:9 frame edge-to-edge, painted style with clean vector shapes, dark forest green (#1f4b37) and sage green (#4a7c4e) tones, yellow-mustard (#e8c547) accents, beige (#e8e4d8) buildings and valleys, white highlights. No text, no watermark, no logos, no borders, no frame.";
// ---- Stadt-Profile mit Szenen-Beschreibung ----
$CITIES = [
'linz' => [
'label' => 'Linz an der Donau',
'scene' => "Scene: Wide panoramic view over the city of Linz, the Danube river curving through the foreground reflecting the sunset, the Pöstlingberg pilgrimage church with its twin towers prominently on a wooded hill on the left, the Mariendom cathedral with its tall slender Gothic spire rising from the city center, large industrial silhouettes of steel works on the right edge, soft alpine foothills in the background.",
],
'klagenfurt' => [
'label' => 'Klagenfurt am Wörthersee',
'scene' => "Scene: Wide panoramic view over the city of Klagenfurt. The illustration must fill the ENTIRE 16:9 frame edge-to-edge with the landscape — no oval frame, no circular vignette, no decorative border, no color palette swatches, no color reference bars at top or bottom, no margins. Just the full-bleed landscape painting from corner to corner. Content: the turquoise Wörthersee lake filling the foreground, several sailing boats on the water, the Lindwurm dragon stone fountain prominently in the central square, city buildings with church towers along the lakeshore, the Karawanken mountain range as a long jagged silhouette in the background.",
],
'stpoelten' => [
'label' => 'Sankt Pölten',
'scene' => "Scene: Wide panoramic view over Sankt Pölten with the cathedral and its tall baroque tower in the city center, the modern government quarter with its distinctive white tower buildings on one side, the Traisen river curving through the foreground, gentle wooded hills in the background.",
],
'bregenz' => [
'label' => 'Bregenz am Bodensee',
'scene' => "Scene: Wide panoramic view over Bregenz on the shore of Lake Constance, the floating Seebühne open-air stage on the lake prominently in the foreground, the Pfänder mountain rising directly from the lakeside in the background, sailboats on the water, layered alpine peaks behind.",
],
'eisenstadt' => [
'label' => 'Eisenstadt im Burgenland',
'scene' => "Scene: Wide panoramic view over Eisenstadt with the yellow Esterházy Palace and its symmetrical façade prominently in the center, vineyard rows in the foreground, gentle rolling Burgenland hills covered with grape vines in the background, soft warm afternoon light.",
],
'villach' => [
'label' => 'Villach an der Drau',
'scene' => "Scene: Wide panoramic view over Villach with the Drau river crossed by the historic stone bridge in the foreground, the Stadtpfarrkirche Sankt Jakob church tower rising prominently in the center, the Karawanken mountain range as a sharp jagged silhouette in the background.",
],
'wels' => [
'label' => 'Wels in Oberösterreich',
'scene' => "Scene: Wide panoramic view over Wels with the Ledererturm medieval city gate tower prominently in the city center, the broad central market square with historic baroque facades, the Traun river curving in the foreground, the Alps as a soft distant silhouette.",
],
'dornbirn' => [
'label' => 'Dornbirn in Vorarlberg',
'scene' => "Scene: Wide panoramic view over Dornbirn with the iconic Rotes Haus, a red half-timbered building, prominently in the central market square, the Karren mountain cable car climbing the slope on one side, the wide green Rheintal valley in the foreground, alpine peaks in the distance.",
],
'wiener_neustadt' => [
'label' => 'Wiener Neustadt',
'scene' => "Scene: Wide panoramic view over Wiener Neustadt with the medieval castle ruin and its surrounding stone walls prominently on a low hill in the center, the historic city ramparts visible, the wide flat Wiener Becken lowland in the foreground, gentle hills in the background.",
],
'steyr' => [
'label' => 'Steyr in Oberösterreich',
'scene' => "Scene: Wide panoramic view over Steyr at the confluence of the Steyr and Enns rivers prominently in the foreground, the Bummerlhaus a tall pointed-roof gothic merchant house in the historic main square, layered medieval roofs and church towers, wooded hills in the background.",
],
'feldkirch' => [
'label' => 'Feldkirch in Vorarlberg',
'scene' => "Scene: Wide panoramic view over Feldkirch with the Schattenburg medieval castle perched prominently on a wooded hill above the old town, narrow medieval streets and red rooftops below, the Ill river curving in the foreground, sharp alpine peaks of the Rätikon range in the background.",
],
'leoben' => [
'label' => 'Leoben in der Steiermark',
'scene' => "Scene: Wide panoramic view over Leoben with the historic Mautturm bridge tower prominently at the Mur river crossing in the foreground, the curved Mur river dominating the scene, the distinctive red-stepped Erzberg iron mountain visible as a silhouette in the background.",
],
];
$outDir = __DIR__ . '/../sims/heli/assets/cities-panorama';
if (!is_dir($outDir)) mkdir($outDir, 0777, true);
$ids = isset($_GET['ids']) ? array_filter(array_map('trim', explode(',', $_GET['ids']))) : array_keys($CITIES);
$force = !empty($_GET['force']);
echo "Stadt-Panorama-Generator (DALL-E 3, 1792x1024)\n";
echo "Modus: " . ($force ? 'FORCE' : 'skip if exists') . "\n";
echo "Auswahl: " . implode(', ', $ids) . "\n";
echo str_repeat('-', 64) . "\n";
@ob_flush(); @flush();
$ok = 0; $skip = 0; $fail = 0;
foreach ($ids as $id) {
if (!isset($CITIES[$id])) { echo "x $id: unbekannt\n"; $fail++; continue; }
$out = $outDir . '/' . $id . '.png';
if (file_exists($out) && !$force) {
echo "skip $id.png (vorhanden)\n";
$skip++;
continue;
}
$prompt = $STYLE . ' ' . $CITIES[$id]['scene'];
$body = json_encode([
'model' => 'dall-e-3',
'prompt' => $prompt,
'n' => 1,
'size' => '1792x1024',
'quality' => 'standard',
]);
echo "-> $id (" . $CITIES[$id]['label'] . ") generiere ... ";
@ob_flush(); @flush();
$ch = curl_init('https://api.openai.com/v1/images/generations');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $OPENAI_KEY,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 180,
]);
$resp = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 200) {
echo "FAIL ($code) — " . substr($resp, 0, 200) . "\n";
$fail++;
continue;
}
$data = json_decode($resp, true);
$url = $data['data'][0]['url'] ?? null;
if (!$url) { echo "FAIL keine URL\n"; $fail++; continue; }
$img = @file_get_contents($url);
if (!$img || strlen($img) < 1000) { echo "FAIL Download\n"; $fail++; continue; }
file_put_contents($out, $img);
$ok++;
echo "ok (" . round(strlen($img) / 1024) . " kB)\n";
@ob_flush(); @flush();
sleep(2);
}
echo str_repeat('-', 64) . "\n";
echo "Zusammenfassung: ok=$ok, skip=$skip, fail=$fail\n";
echo "Ordner: $outDir\n";