Files
geograsim/App/scripts/generate-3-cards.py
T
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

88 lines
5.3 KiB
Python

#!/usr/bin/env python3
"""Generiert 3 Modul-Karten-Bilder (Fluggesellschaft, Vulkan, Wal) im GeoGraSim-Flat-Scandinavian-Stil.
Aufruf: python App/scripts/generate-3-cards.py
"""
import json, os, subprocess, sys, tempfile
# Key aus .env.local lesen
KEY = None
env_path = 'C:/xampp/htdocs/geograsim/App/.env.local'
with open(env_path, 'r', encoding='utf-8') as f:
for line in f:
if line.startswith('OPENAI_API_KEY='):
KEY = line.split('=', 1)[1].strip().strip('"').strip("'")
break
if not KEY:
sys.exit('OPENAI_API_KEY nicht in .env.local')
OUT_DIR = 'C:/xampp/htdocs/geograsim/App/assets/img'
PROMPT_BASE = ("CRITICAL STYLE: flat vector illustration, children's-book / Scandinavian poster art, "
"NO photography, NO 3D rendering, NO realistic shading, NO photographic textures, NO gradients except very subtle sky. "
"Style is wide-shape silhouettes with flat solid color fills, clean cut edges, simple geometric forms. "
"Strict palette: dark forest green #1f4b37, sage green #4a7c4e, yellow-mustard #e8c547, beige #e8e4d8, white highlights. "
"Composition fills the entire 16:9 frame edge-to-edge. "
"FORBIDDEN: text, letters, numbers, watermarks, logos, borders, frames, photo-realistic lighting, lens-flare, "
"people faces with detail, brand names.")
PROMPTS = {
'card-fluggesellschaft.png': (PROMPT_BASE + " SCENE (flat illustration): A stylised passenger airliner silhouette, "
"side view, climbing toward upper-right corner, simple shapes — fuselage as one solid forest-green shape, "
"tail and wings as cleanly cut sage-green and yellow-mustard accents. "
"Below: a wide flat horizon line, a soft cluster of stylised European city silhouettes (small triangular roofs, "
"one cathedral spire, simple round church tower) in beige and sage. "
"Sky: a flat very pale sage-green to white gradient. Two or three minimalist arc-lines in yellow-mustard "
"across the sky suggesting great-circle routes (just thin dotted curves). "
"No clouds with depth, no realistic plane details, no engines with detail."),
'card-vulkan.png': (PROMPT_BASE + " SCENE (flat illustration): A symmetrical stylised stratovolcano cone filling most of the lower half, "
"two flat color bands — forest-green base and sage-green upper slope — with one bold yellow-mustard zigzag lava streak "
"down the right flank. The crater is a small yellow-mustard semicircle at the peak. "
"Rising from the crater: a soft beige-and-white ash plume as 3-4 stacked rounded shapes (NOT realistic smoke). "
"Sky: flat pale background. "
"At the base, a small row of beige flat houses with triangular sage roofs. "
"No realistic textures, no glowing fire, no smoke particles, no detailed rocks."),
'card-wal.png': (PROMPT_BASE + " SCENE (flat illustration): A large stylised humpback whale silhouette in dark forest-green, "
"shown side-view in a graceful breaching arc, occupying the centre. The whale body is ONE solid flat shape, "
"with one small yellow-mustard belly accent and one white eye dot — no scales, no muscle detail, no realistic skin. "
"Below the whale: a flat sage-green ocean band with simple wave shapes (curved lines in dark green). "
"Above: flat pale sky. A tiny minimalist cargo-ship silhouette in beige on the horizon line, "
"far to one side. No splash with droplets, no realistic water, no detailed clouds."),
}
import base64
def generate(filename, prompt):
out = os.path.join(OUT_DIR, filename)
body = json.dumps({'model': 'gpt-image-2', 'prompt': prompt, 'n': 1, 'size': '1536x1024'}, ensure_ascii=False)
with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', suffix='.json', delete=False) as f:
f.write(body); bpath = f.name
r = subprocess.run(['curl', '-sS',
'-X', 'POST', 'https://api.openai.com/v1/images/generations',
'-H', 'Authorization: Bearer ' + KEY,
'-H', 'Content-Type: application/json',
'--data-binary', '@' + bpath], capture_output=True, text=True, timeout=300)
os.unlink(bpath)
try:
data = json.loads(r.stdout)
item = data['data'][0]
if 'b64_json' in item:
with open(out, 'wb') as f:
f.write(base64.b64decode(item['b64_json']))
elif 'url' in item:
subprocess.run(['curl', '-sS', '-o', out, item['url']], capture_output=True, text=True, timeout=60)
else:
return False, f'kein Bild im Response: {list(item.keys())}'
except Exception as e:
err = r.stdout[:300] if r.stdout else str(e)
return False, f'API-Fehler: {err}'
if not os.path.exists(out) or os.path.getsize(out) < 10000:
return False, 'Download fehlgeschlagen'
return True, f'{os.path.getsize(out)//1024}K'
for fn, pr in PROMPTS.items():
print(f'-> {fn} ...', flush=True)
ok, msg = generate(fn, pr)
print(f' {"OK" if ok else "FAIL"}: {msg}')