1e51ef7def
- 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>
71 lines
4.0 KiB
Python
71 lines
4.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Generiert die Card für das Weltküche-Modul im GeoGraSim-Flat-Scandinavian-Stil.
|
|
Aufruf: python App/scripts/generate-weltkueche-card.py
|
|
Output: App/assets/img/card-weltkueche.png (wird anschließend zu .webp konvertiert)
|
|
"""
|
|
import json, os, subprocess, sys, tempfile, base64
|
|
|
|
# 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.")
|
|
|
|
PROMPT = (PROMPT_BASE + " SCENE (flat illustration): A stylised wooden plate or large round bowl in the centre, "
|
|
"viewed top-down or slightly tilted. On the plate: a small composition of flat-shape food items from around the world — "
|
|
"one round forest-green leaf (basil), two small yellow-mustard wedges (citrus/spice), three small beige bread/grain shapes, "
|
|
"one sage-green slice (vegetable), one round dark-green olive or seed. "
|
|
"All food shapes are SIMPLE flat silhouettes with solid color fills — no texture, no gloss, no realistic detail. "
|
|
"Around the plate, in the background: a flat earthy beige tablecloth or wood-grain surface in beige, with three or four "
|
|
"tiny minimalist symbols suggesting different cultures spread on the table — "
|
|
"a single small yellow-mustard star, a tiny forest-green leaf sprig, one tiny sage-green bowl outline. "
|
|
"All food items are arranged like a clean infographic. NO faces, NO hands, NO text. "
|
|
"Vibe: didactic, calm, warm, world-food curiosity.")
|
|
|
|
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'
|
|
|
|
print('-> card-weltkueche.png ...', flush=True)
|
|
ok, msg = generate('card-weltkueche.png', PROMPT)
|
|
print(f' {"OK" if ok else "FAIL"}: {msg}')
|