Files
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

98 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Stadt-Symbolbilder fuer Busfahrt.
Liest cities.json, generiert fuer jede Stadt mit imagePrompt das fehlende
Bild via DALL-E-3 im verbindlichen GeoGraSim-Bildstil.
Aufruf:
set -a; source App/.env.local; set +a
python3 App/sims/busfahrt/scripts/generate-city-images.py # alles fehlende
python3 App/sims/busfahrt/scripts/generate-city-images.py tokio rom # gezielt
Ueberschreiben: FORCE=1 python3 ... tokio
"""
import json, os, sys, time, urllib.request, urllib.error
KEY = os.environ.get('OPENAI_API_KEY')
if not KEY:
sys.exit('OPENAI_API_KEY env var nicht gesetzt — vorher: set -a; source App/.env.local; set +a')
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
CITIES_FILE = os.path.join(SCRIPT_DIR, '..', 'assets', 'data', 'cities.json')
IMG_DIR = os.path.join(SCRIPT_DIR, '..', 'assets', 'cities')
os.makedirs(IMG_DIR, exist_ok=True)
with open(CITIES_FILE, encoding='utf-8') as f:
cities = json.load(f)
force = os.environ.get('FORCE') == '1'
arg_targets = set(sys.argv[1:])
todo = []
for city in cities:
if not city.get('imagePrompt'):
continue
if arg_targets and city['id'] not in arg_targets:
continue
out_path = os.path.join(IMG_DIR, f"{city['id']}.png")
if os.path.exists(out_path) and not force:
continue
todo.append((city, out_path))
if not todo:
print("nichts zu tun — alle Bilder vorhanden (FORCE=1 zum Ueberschreiben)")
sys.exit(0)
print(f"-> generiere {len(todo)} Bilder ...")
ok_count = 0
fail_count = 0
for i, (city, out_path) in enumerate(todo, 1):
print(f"[{i}/{len(todo)}] {city['id']}: ", end='', flush=True)
payload = json.dumps({
"model": "dall-e-3",
"prompt": city['imagePrompt'],
"n": 1,
"size": "1792x1024",
"quality": "standard",
}).encode()
req = urllib.request.Request(
"https://api.openai.com/v1/images/generations",
data=payload,
headers={
"Authorization": f"Bearer {KEY}",
"Content-Type": "application/json",
},
)
try:
with urllib.request.urlopen(req, timeout=180) as resp:
data = json.loads(resp.read().decode())
url = data['data'][0]['url']
except urllib.error.HTTPError as e:
body = e.read().decode()
print(f"x HTTP {e.code}{body[:200]}")
fail_count += 1
time.sleep(5)
continue
except Exception as e:
print(f"x {e}")
fail_count += 1
time.sleep(5)
continue
try:
urllib.request.urlretrieve(url, out_path)
size = os.path.getsize(out_path)
print(f"ok ({size//1024} KB)")
ok_count += 1
except Exception as e:
print(f"x download {e}")
fail_count += 1
continue
time.sleep(2.5)
print(f"\nFertig: {ok_count} ok, {fail_count} Fehler")