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>
276 lines
32 KiB
PHP
276 lines
32 KiB
PHP
<?php
|
||
/**
|
||
* Glossar-Bilder-Generator (DALL-E 3, Querformat 1792x1024).
|
||
* Bildstil aus reference_bildstil.md — Flat Scandinavian, Forest/Sage/Mustard/Beige.
|
||
*
|
||
* Aufruf:
|
||
* /php/generate-glossar-images.php → alle Slugs ohne Bild generieren
|
||
* /php/generate-glossar-images.php?ids=monokultur,mangrove → Auswahl
|
||
* /php/generate-glossar-images.php?ids=...&force=1 → überschreibt vorhandene
|
||
* /php/generate-glossar-images.php?max=10 → höchstens 10 generieren (Test/Batch)
|
||
*/
|
||
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 gesetzt\n"); }
|
||
|
||
// Verbindlicher Stil-Block (verbatim aus reference_bildstil.md), MIT zusätzlichem
|
||
// expliziten "no frame, no border" als Mantra (Mangrove-Test-Lauf hatte Rahmen).
|
||
$STYLE_BASE = "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. The image must reach the edges with no decorative frame, no border, no inner margin, no vignette. No text, no watermark, no logos.";
|
||
|
||
// Szenen-Suffixe pro Glossar-Slug (114 Einträge ohne image_path).
|
||
// Jeweils 1–2 Sätze, was zu sehen ist. Konsequent englisch für DALL-E.
|
||
$SCENES = [
|
||
// ===== Astronomie (10) =====
|
||
'achsneigung' => "Subject: Earth in space tilted on its 23.5-degree axis, sun rays striking the planet from one side, four small Earth icons around showing the four seasons.",
|
||
'astronomische-einheit' => "Subject: a horizontal scale drawing of the inner solar system, Sun on the left, Earth in the middle with a labeled distance arrow, Mars and Jupiter further right, sense of scale and emptiness.",
|
||
'ekliptik' => "Subject: a diagonal celestial band across the sky showing the path of the Sun and planets, stars scattered above and below, the zodiacal plane indicated as a soft sage-green ring.",
|
||
'mondfinsternis' => "Subject: a total lunar eclipse view, Earth in the middle casting its shadow across a glowing reddish moon to the right, Sun on the far left, all three aligned, dark night sky with subtle stars.",
|
||
'mondphase' => "Subject: eight phases of the moon arranged in a horizontal row from new moon to full moon and back, dark night sky background, soft beige craters visible.",
|
||
'polarkreis' => "Subject: a globe seen from the side showing the Arctic Circle as a glowing line at 66.5 degrees north, snow and ice cap above, dark forest green continents below, sun at low angle.",
|
||
'sonnenfinsternis' => "Subject: a solar eclipse during totality, the dark moon perfectly covering the bright sun, white corona radiating outward, distant Earth landscape silhouette below in sage-green.",
|
||
'sonnenwende' => "Subject: an Earth diagram with sun rays striking strongest at the Tropic of Cancer, summer solstice scene, long shadows on the surface, golden mustard sunlight from upper left.",
|
||
'tag-und-nacht-gleiche' => "Subject: an Earth diagram with sun rays striking exactly at the equator, day and night halves perfectly equal, soft transition line from light to shadow across the planet.",
|
||
'wendekreis' => "Subject: a globe seen from the front showing the two tropical lines (Tropic of Cancer and Capricorn) as glowing horizontal bands, sun directly above the equator at midday.",
|
||
|
||
// ===== Biologie (7) =====
|
||
'aquakultur' => "Subject: a Norwegian fjord with circular fish farm pens floating on the water, dark forest-green forested mountains rising behind, a small service boat near the pens.",
|
||
'bodenmuedigkeit' => "Subject: a cracked dry brown agricultural field with thin pale yellow stalks, a healthy green field with red clover next to it for comparison, simple split composition.",
|
||
'eignungsklasse' => "Subject: a stylized world map subdivided into colored agricultural suitability zones (deep green for very suitable, pale beige for marginal, white for not suitable), small crop icons placed in each zone.",
|
||
'krankheits-ausbruch' => "Subject: a banana plantation with rows of palm trees, several plants drooping and yellow with the Panama disease, healthy plants in the background, contrast between sick and healthy.",
|
||
'monokultur' => "Subject: an endless agricultural field of a single crop seen from low aerial perspective, perfectly straight long rows of identical green corn plants stretching to the horizon, geometric repeating pattern, one solitary harvester machine far in the distance, low rolling beige hills along the horizon, clear sky.",
|
||
'oekosystem' => "Subject: a riparian woodland with a winding river, deer drinking at the bank, herons in the shallows, oaks and willows, dragonflies, full of biodiversity in soft Scandinavian palette.",
|
||
'ueberweidung' => "Subject: a Sahel landscape with too many goats and cattle on a sparse, almost bare brown ground, a single thorn tree, clear sense of overgrazed land, faint dust in the air.",
|
||
|
||
// ===== Einheit (5) =====
|
||
'co2-aequivalent' => "Subject: a balance scale with one CO2 cloud icon on the left and a smaller methane cloud icon on the right, the scales clearly tipping toward the methane (because it is much more potent), sky background.",
|
||
'luftlinie' => "Subject: a map of central Europe with two cities marked by dots, a perfectly straight dashed yellow-mustard line between them as airline distance, forested terrain visible below.",
|
||
'massstab' => "Subject: a topographic map of an alpine region next to a real landscape view of the same area, a labeled scale bar at the bottom, sense of relation between map and reality.",
|
||
'umweg' => "Subject: a winding road through a hilly landscape with a long curving detour around a steep mountain, a straight dashed line cutting across as comparison airline distance, contrast between actual route and shortcut.",
|
||
'wirkungsgrad' => "Subject: a horizontal pie diagram showing energy flow, a large mustard yellow band labeled as useful energy and a smaller dark area as heat loss, simple infographic style with labels removed.",
|
||
|
||
// ===== Energie (15) =====
|
||
'blackout' => "Subject: a city skyline at night completely dark, no lights in the buildings, only a few candles flickering in distant windows, full moon, eerie quiet atmosphere.",
|
||
'dunkelflaute' => "Subject: a still winter landscape under a dense overcast sky, three motionless white wind turbines on a sage-green hillside with bare leafless trees, no movement, dim diffuse twilight, faint snow flurries in the air, a single farmhouse with warm yellow window light in the valley below, mood of quiet and standstill.",
|
||
'erneuerbar' => "Subject: a panoramic landscape with wind turbines on hills, solar panels on a rooftop, a hydropower dam in a valley, all together harmoniously in one frame, sun shining over forests.",
|
||
'grundlast' => "Subject: a wide power consumption chart skyline, a steady horizontal mustard line at the bottom representing constant base demand, with peaks for morning and evening rising above it, factories and homes silhouetted below.",
|
||
'kohlekraftwerk' => "Subject: a coal-fired power plant complex with two large cooling towers releasing thick white steam, a single tall chimney with dark smoke, dark sage-green industrial buildings, sense of bulk and weight.",
|
||
'lastausgleich' => "Subject: a horizontal balance beam with a wind turbine on one side and a glowing city on the other, perfectly balanced, sense of supply and demand matching in real time, simple symbolic.",
|
||
'lastprofil' => "Subject: a clean horizontal graph curve showing electricity demand over a day, two prominent peaks at 8 in the morning and 7 in the evening, a low valley at 3 a.m., subtle backdrop of city silhouette behind the curve.",
|
||
'pumpspeicher' => "Subject: an alpine pumped-storage hydro plant, a high mountain reservoir at the top, a lower lake at the bottom, large pipes connecting them down the slope, machine hall at the base, snow caps above.",
|
||
'regelreserve' => "Subject: a control center with multiple monitors showing grid frequency, several technicians watching, a backup power station seen through a window outside, sense of standby readiness.",
|
||
'residuallast' => "Subject: a horizontal stacked area chart, a wide green wind-and-solar layer covering most of the demand, a thin remaining mustard band on top representing the gap that must be filled, gentle landscape behind.",
|
||
'solaranlage' => "Subject: a residential rooftop covered in dark-green solar panels reflecting the bright sky, a sun in the upper corner with golden mustard rays, a green garden and beige house below.",
|
||
'spitzenlast' => "Subject: a clean horizontal graph curve showing electricity demand peaking sharply at 7 in the evening, a city skyline behind with all windows lit up at the same time, sense of simultaneity.",
|
||
'strom' => "Subject: high-voltage power transmission lines striding across a wide rural landscape, four steel pylons in a row, sage-green fields below, soft beige sky.",
|
||
'stromnetz' => "Subject: a continental scale electrical grid, glowing yellow lines connecting major European cities, dark sage-green continents, network nodes visible.",
|
||
'stromspeicher' => "Subject: three storage technologies side by side in panoramic composition: a large mountain reservoir on the left, a row of battery containers in the middle, a hydrogen storage tank on the right.",
|
||
'turbine' => "Subject: a cross-section view of a large hydropower turbine, blue water flowing through curved blades, the rotor in the center, electrical generator above, dark forest-green machinery housing.",
|
||
'windpark' => "Subject: a row of seven large white wind turbines on a wide rolling hillside, distant green forests behind, soft beige sky, sense of clean steady power generation.",
|
||
|
||
// ===== Geologie / Heli (10) =====
|
||
'breitengrad' => "Subject: a globe seen from the front with horizontal latitude lines clearly drawn, the equator highlighted in mustard yellow, the tropics and Arctic Circle as fainter horizontal bands.",
|
||
'einsatzkoordinate' => "Subject: a topographic alpine map with a red dot marking an emergency rescue location at high altitude, coordinate grid drawn over the map, a small helicopter icon flying toward the dot.",
|
||
'gps' => "Subject: a stylized Earth from space with three GPS satellites in orbit beaming signals down to a small handheld receiver on the ground, the receiver glowing softly with a position fix.",
|
||
'gradnetz' => "Subject: a globe with both latitude and longitude lines forming a clear geographic grid, prime meridian highlighted in mustard yellow, the equator highlighted in white, dark forest-green continents.",
|
||
'hoehenlinie' => "Subject: a topographic map of an alpine region with concentric brown contour lines around a mountain peak, dense lines indicating steep slopes, sparse lines on a flat valley, classical cartographic look.",
|
||
'hoehenstufe' => "Subject: a vertical mountain cross-section with four altitudinal vegetation belts: green forest at the bottom, dark conifers higher, alpine meadows above, snow and rock at the summit.",
|
||
'kompass' => "Subject: a classical magnetic compass with a needle pointing to the north, lying on a folded topographic map next to a wooden hiking pole and a thermos, soft natural light.",
|
||
'koordinate' => "Subject: a topographic European map with a single red pin marking Vienna, coordinate values 48 N 16 E discretely drawn next to it, latitude and longitude lines visible across the map.",
|
||
'laengengrad' => "Subject: a globe seen from above the North Pole with vertical longitude meridians radiating outward like spokes, the prime meridian through Greenwich highlighted in mustard yellow.",
|
||
'topografische-karte' => "Subject: a paper topographic map of an alpine valley laid out on a wooden table, contour lines, forests symbols, blue rivers, a small village mark, a red wandering trail across.",
|
||
'topografie' => "Subject: an aerial view of a varied landscape showing all major topographic forms in one frame, snow-capped mountains in the back, forested hills, a winding river, flat plains with farms, a coastline with sandy beach, sense of land surface diversity.",
|
||
|
||
// ===== Gesellschaft (12) =====
|
||
'bevoelkerung' => "Subject: a panoramic crowd of stylized human figures in different colors, all walking in the same direction, sense of population mass, soft sage-green and beige tones.",
|
||
'eu-gesetz' => "Subject: a stack of bound legal documents with the EU stars logo on the cover stamped in mustard yellow, a wax seal, lying on a wooden parliament desk.",
|
||
'eu-kommission' => "Subject: the Berlaymont building, the EU Commission headquarters in Brussels, glass star-shaped façade clearly visible, EU flags lined up in the foreground.",
|
||
'eu-parlament' => "Subject: the European Parliament hemicycle in Strasbourg with rows of curved seats arranged in a semicircle, all seats occupied with stylized members raising their hands to vote, EU flag in the back.",
|
||
'eu-petition' => "Subject: a long handwritten signed paper petition rolled out, dozens of signatures filling the page, lying in front of the European Parliament Strasbourg building.",
|
||
'eu-zustaendigkeit' => "Subject: a stylized two-circle Venn diagram, one circle labeled EU and one labeled member states, the overlap area glowing mustard yellow as shared competence.",
|
||
'europaeische-buergerinitiative' => "Subject: a large gathering of citizens in a public square holding clipboards collecting signatures, an EU flag in the background, sense of grassroots democracy.",
|
||
'europaeischer-rat' => "Subject: an oval conference table where heads of state from many European countries are seated, name plates and small national flags in front of each, large EU flag on the back wall.",
|
||
'freiwillige-vereinbarung' => "Subject: two business people shaking hands across a wooden table, an open contract document between them, soft natural office light, sense of voluntary mutual agreement.",
|
||
'initiativrecht' => "Subject: a single stylized person at a podium pointing forward, holding up a fresh draft law, EU stars on the wall behind, the start of the legislative process visualized.",
|
||
'lobbyismus' => "Subject: business representatives whispering to a politician outside a parliament building, briefcases and folders changing hands, slightly tense atmosphere, EU flag visible.",
|
||
'mitentscheidung' => "Subject: two equal stylized chambers facing each other, the European Parliament on the left, the Council of the EU on the right, both stamping the same draft law in the middle.",
|
||
'rat-der-eu' => "Subject: a meeting room with national ministers seated around a large round table, name plates and country flags, EU stars logo above, sense of intergovernmental coordination.",
|
||
|
||
// ===== Klima (10) =====
|
||
'co2_filter' => "Subject: a large industrial CO2 capture facility with several tall absorption towers, a pipeline leading underground to a storage formation, factory buildings in beige, sage-green hills behind.",
|
||
'klimafolgen' => "Subject: a triptych panoramic landscape, on the left a flooded coastal village, in the middle a parched cracked field, on the right a forest fire smoke plume, sense of cascading climate impacts.",
|
||
'klimazone' => "Subject: a stylized world map with five horizontal climate zones in different shades of green and beige, palm trees marking tropics, conifers marking temperate, ice caps marking polar regions.",
|
||
'koeppen-geiger' => "Subject: a stylized world map subdivided into the major Köppen-Geiger climate zones in distinct sage-green shades, simple labels removed, smooth coloring.",
|
||
'kuestenschutz' => "Subject: a long earthen dike along a coastline with the rough sea on one side and protected farmland and houses on the other, white waves crashing against the dike, low sun.",
|
||
'mangrove' => "Subject: a tropical coastline of mangrove trees with characteristic stilt roots rising from shallow turquoise saltwater, dense canopy of small dark forest-green leaves, sandy beige beach in the background, gentle ripples in the water, soft sunlight from the side, distant calm sea horizon.",
|
||
'meeresspiegel' => "Subject: a coastal city with a clearly marked old water level on the harbor wall and the new much higher current sea level, a couple of gulls flying, mood of slow steady rise.",
|
||
'subtropisch-cfa' => "Subject: a Northern Italian Po valley landscape, wide rice paddies, rows of poplar trees, a farmhouse with red roof, distant beige Alps, warm humid summer atmosphere.",
|
||
'temperatur' => "Subject: a large wall thermometer in a wide landscape, mercury column rising into a dark red zone, sun beating down, dry brown grass below, sense of warming.",
|
||
'ueberflutung' => "Subject: a flooded village street with submerged ground floors, rooftops poking out of the water, a small rescue boat, drowned trees, gray dramatic sky.",
|
||
|
||
// ===== Stadt (11) =====
|
||
'flaechenwidmung' => "Subject: an aerial view of a planned town divided into colored zones: residential blocks in beige, industrial in dark gray, green park areas in sage, all clearly delimited by streets.",
|
||
'hauptstadt' => "Subject: a calm panoramic view of a European capital city skyline at midday, elegant parliament building with a large beige dome and twin towers in the center, classical bridge crossing a wide river in the foreground, low forested hills behind the city, soft daylight, no people visible.",
|
||
'nahversorgung' => "Subject: a charming pedestrian city street with a bakery, pharmacy, and small grocery store side by side, an elderly person and a child with a basket walking, sense of daily errands within walking distance.",
|
||
'nutzungskonflikt' => "Subject: a piece of land with a fence in the middle, on one side an architect waving plans for an apartment building, on the other side a farmer next to a tractor, both gesturing toward the same field, midday sun.",
|
||
'oepnv' => "Subject: a modern tram crossing a city square with passengers boarding and stepping off, beige historic buildings around, a metro entrance visible at the corner, smooth flow of movement.",
|
||
'pendler' => "Subject: a quiet train platform at early morning, a regional commuter train just arriving at the station, a small group of standing figures with backpacks and shoulder bags waiting, distant city skyline of beige low-rise buildings behind, cool dawn light, soft long shadows.",
|
||
'siedlungsdichte' => "Subject: an aerial view comparing dense city blocks of tall apartment buildings on the left and sparse suburban single-family houses with large gardens on the right, clear contrast.",
|
||
'urbanisierung' => "Subject: a horizontal time-lapse landscape, on the left a small village in the year 1900, transitioning across to a sprawling modern megacity on the right, with a long winding road through the middle.",
|
||
'verdichtung' => "Subject: a city block where two old low buildings stand next to a new tall apartment tower being built on the same plot, a crane in operation, sense of more housing on the same land.",
|
||
'wahrzeichen' => "Subject: the Eiffel Tower in Paris from the Trocadéro side, the iconic latticed iron silhouette filling most of the frame, the Seine river curving below, a few distant Parisian rooftops.",
|
||
'zersiedelung' => "Subject: an aerial view of suburban sprawl, isolated single-family houses scattered across former farmland, long winding access roads, a dying small village center in the middle, sense of fragmented landscape.",
|
||
|
||
// ===== Wasser (8) =====
|
||
'einzugsgebiet' => "Subject: a watershed map with a network of streams converging from many directions into one main river, dashed lines marking the watershed boundary along ridge tops, sage-green forested terrain.",
|
||
'hafen' => "Subject: a busy European seaport at midday with a large container ship being unloaded, several gantry cranes lifting boxes, stacked containers in mustard yellow and forest green, calm water reflecting.",
|
||
'hochwasserschutz' => "Subject: a river with a tall earthen dike and a sluice gate, beyond the dike a peaceful village, on the riverside a designated retention meadow with willows, water level just below the dike top.",
|
||
'maeander' => "Subject: an aerial view of a winding river forming several large meander loops in a wide green floodplain, oxbow lakes visible from previous loops, lush riparian forest along the banks.",
|
||
'renaturierung' => "Subject: a river that was once straight, now showing newly created meanders, freshly planted young trees along the banks, the old straight channel still partially visible, sense of restoration.",
|
||
'retention' => "Subject: a controlled flooded retention meadow next to a river, water spread across a large grassy area, a few willows knee-deep in water, a peaceful village protected on higher ground in the distance.",
|
||
'ueberschwemmungsgebiet' => "Subject: an aerial view of a river floodplain naturally inundated with shallow water, scattered trees, a meandering river in the center, beige farmland on higher ground beyond.",
|
||
'ufervegetation' => "Subject: a riverbank with dense reeds, willows, and alder trees, their roots stabilizing the bank, a kingfisher on a low branch, sunlight filtering through the leaves.",
|
||
|
||
// ===== Wirtschaft (16) =====
|
||
'auftrag' => "Subject: a single freight order document on a clipboard with origin, destination, deadline, and price filled in, a forklift moving a container in the background, warehouse setting.",
|
||
'bahnterminal' => "Subject: a freight rail terminal with a long line of container wagons, a tall portal crane lifting a container onto a waiting truck, beige warehouses behind, dawn light.",
|
||
'budget' => "Subject: a stylized municipal budget infographic, a large mustard-yellow bar split into colored segments labeled invisibly for schools, roads, parks, and energy, a city silhouette below.",
|
||
'container' => "Subject: a stack of forty standardized shipping containers in mustard yellow, deep forest green, and white, neatly arranged in a port yard, gantry crane silhouette behind.",
|
||
'disposition' => "Subject: a logistics dispatcher at a desk with multiple monitors showing maps and routes, sticky notes with order numbers, soft warm desk lamp, focused atmosphere.",
|
||
'fahrzeug' => "Subject: a side-by-side panorama of a freight truck on a road, a freight train on rails, and a container ship at sea, all in the same frame, comparing capacities visually.",
|
||
'frist' => "Subject: a large hourglass with golden sand running down halfway, a freight container with a deadline tag in the background, sense of time pressure but not stressful.",
|
||
'importpreis-abschlag' => "Subject: a market shelf with two tomato baskets side by side, one labeled with a higher price tag from local Tirol farm, one with a lower price tag from Morocco, customer hand reaching for the cheaper one.",
|
||
'logistik' => "Subject: a warehouse hub with truck bays on both sides, forklifts moving pallets, conveyor belts, organized stacks of boxes in mustard yellow and beige, sense of orchestrated movement.",
|
||
'marge' => "Subject: a balance scale with a stack of euro coins on the left labeled price and a smaller stack on the right labeled cost, the difference highlighted in mustard yellow as profit margin.",
|
||
'reefer-container' => "Subject: a refrigerated shipping container with a small power unit and visible cooling fins, snowflake symbol on the door, fresh bananas and avocados glimpsed inside through opened doors.",
|
||
'routing' => "Subject: a road map of central Europe with one route highlighted in mustard yellow snaking around mountains and lakes, a straight dashed line as airline distance for comparison, two pin markers at the endpoints.",
|
||
'spedition' => "Subject: a freight forwarding company office with desks, employees on phones, a large wall map of Europe with pins, fleet of trucks visible through a glass door outside.",
|
||
'standkosten' => "Subject: a single shipping container sitting motionless in an empty port yard, a small calendar on the side ticking off days, faint dust accumulating on top, sense of waiting and accruing cost.",
|
||
'steuern' => "Subject: a hand dropping a coin into a small jar labeled with a tiny city silhouette, surrounded by symbols of public services like a school, a bus, and a park bench around the jar.",
|
||
'tarif' => "Subject: a clean infographic of a price-per-kilometer chart for buses and trucks, a small bus icon at one end and a destination flag at the other, a clear distance scale below.",
|
||
'tourismus' => "Subject: a coastal beach resort with a few hotels in beige, sun umbrellas in mustard yellow, calm green sea, a sailboat in the distance, mood of summer holiday.",
|
||
'umschlag' => "Subject: a port quay where a tall gantry crane is lifting a single forty-foot container off a moored ship and lowering it onto a waiting train wagon, smooth motion.",
|
||
'verderblich' => "Subject: an opened crate of fresh bananas and tomatoes with a clear timer icon next to them showing only days remaining, refrigerator unit cooling them, sense of urgency.",
|
||
'verkaufspreis' => "Subject: a freight invoice document with the line tariff times distance equals price highlighted, a calculator next to it, a truck driving away in the background.",
|
||
'wartung' => "Subject: a wind turbine maintenance scene, a technician in a harness on the nacelle inspecting the rotor mechanism, helicopter delivering parts in the distance.",
|
||
'welt-hafen' => "Subject: an aerial panoramic view of the port of Rotterdam at midday, dozens of large container ships, gantry cranes, vast stacks of containers, network of canals and roads.",
|
||
|
||
// ===== Entscheidungstag (15) =====
|
||
'waermepumpe' => "Subject: a modern outdoor heat pump unit mounted next to the wall of a beige Scandinavian family house, the unit a sleek rectangular box with a large fan visible, snow on the ground around it, sage-green forest behind, sunny winter day.",
|
||
'pellets' => "Subject: a close-up of a pile of small cylindrical wood pellets glowing warm, a rustic mustard-yellow wooden scoop half-buried in them, a part of the storage bunker in beige wood visible at the edge.",
|
||
'fernwaerme' => "Subject: a cross-section view showing two large insulated district heating pipes running underground beneath a city street, hot water flowing through them visualized as a warm orange tone, a distant heating power plant on the horizon, snowy beige rooftops above.",
|
||
'heizoel' => "Subject: a basement room with a large beige cylindrical heating oil tank in the corner, a small dark forest green oil burner unit next to it with pipes leading up, a single window letting in cool light, technical and sober mood.",
|
||
'erdgas' => "Subject: a wall-mounted gas combi-boiler in a beige utility room, the front cover removed showing a clean blue flame inside, neat copper pipes leading up, mustard-yellow gas pipe entering from the side.",
|
||
'konsum' => "Subject: a busy pedestrian shopping street with several people carrying multiple shopping bags, beige facades with colorful shop windows, parked bicycles, a tram in the distance, mood of consumption and abundance.",
|
||
'beduerfnisse' => "Subject: Maslow hierarchy of needs visualized as a five-tiered pyramid in sage-green and mustard-yellow tones, the bottom tier showing a bowl of food and a bed icon, the middle tier showing two figures holding hands, the top tier showing a single person reaching up.",
|
||
'suffizienz' => "Subject: a calm minimalist Scandinavian living room with very few but high-quality objects, one well-loved armchair, a bookshelf with curated books, a single potted plant, large window letting in soft light, sense of contentment with little.",
|
||
'sparen' => "Subject: a classic ceramic piggy bank in mustard yellow standing on a wooden table, a hand placing a single coin on top, a small green plant growing next to it as metaphor for growth, soft warm afternoon light.",
|
||
'hochrechnung' => "Subject: a clean horizontal bar chart, one tiny bar on the left labeled day, a medium bar in the middle labeled month, a tall bar on the right labeled year, all in mustard-yellow shades, simple infographic style with no readable text.",
|
||
'etf' => "Subject: a stylized globe with translucent overlay of dozens of small company logos and stock-ticker arrows pointing upward, mustard-yellow and forest-green color palette, sense of broad global investment.",
|
||
'mischfonds' => "Subject: a pie chart split into two parts, sixty percent in mustard yellow labeled stocks and forty percent in dark forest green labeled bonds, the chart placed on a wooden desk with a small plant nearby, simple infographic.",
|
||
'zinseszins' => "Subject: a beautiful exponential growth curve rising from left to right, drawn over a wide landscape, the curve made of stacked golden mustard coins growing taller and taller, sense of compounding over time.",
|
||
'mobilitaet' => "Subject: a calm Scandinavian street scene at a multi-modal transport hub, a bus stop with people boarding, a bicycle rack with several bikes, an electric car charging station, a tram passing by, beige low-rise buildings around.",
|
||
'graue-energie' => "Subject: a single smartphone in the center of the frame with translucent ghosted lines connecting it backward to a factory, a freight ship, a mining excavator, and a lithium pit, all in faint sage-green and beige tones, sense of hidden production chain.",
|
||
];
|
||
|
||
$outDir = __DIR__ . '/../assets/img/glossar';
|
||
if (!is_dir($outDir)) mkdir($outDir, 0777, true);
|
||
|
||
$ids = isset($_GET['ids']) && $_GET['ids'] !== ''
|
||
? array_filter(array_map('trim', explode(',', $_GET['ids'])))
|
||
: array_keys($SCENES);
|
||
$force = !empty($_GET['force']);
|
||
$max = isset($_GET['max']) ? max(1, (int) $_GET['max']) : PHP_INT_MAX;
|
||
|
||
echo "Glossar-Bild-Generator (DALL-E 3, 1792x1024, standard quality)\n";
|
||
echo "Modus: " . ($force ? 'FORCE' : 'skip if exists') . " | Limit: " . ($max === PHP_INT_MAX ? 'kein' : $max) . "\n";
|
||
echo "Slugs in Liste: " . count($SCENES) . "\n";
|
||
echo str_repeat('-', 70) . "\n";
|
||
@ob_flush(); @flush();
|
||
|
||
$ok = 0; $skip = 0; $fail = 0; $done = 0;
|
||
foreach ($ids as $id) {
|
||
if ($done >= $max) {
|
||
echo "(Limit $max erreicht — Stopp)\n";
|
||
break;
|
||
}
|
||
if (!isset($SCENES[$id])) {
|
||
echo "x $id: kein Szenen-Prompt definiert\n";
|
||
$fail++;
|
||
continue;
|
||
}
|
||
$out = $outDir . '/' . $id . '.png';
|
||
if (file_exists($out) && !$force) {
|
||
echo "skip $id.png (vorhanden)\n";
|
||
$skip++;
|
||
continue;
|
||
}
|
||
$prompt = $STYLE_BASE . ' ' . $SCENES[$id];
|
||
$body = json_encode([
|
||
'model' => 'dall-e-3',
|
||
'prompt' => $prompt,
|
||
'n' => 1,
|
||
'size' => '1792x1024',
|
||
'quality' => 'standard',
|
||
]);
|
||
echo "-> $id 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++;
|
||
$done++;
|
||
continue;
|
||
}
|
||
$data = json_decode($resp, true);
|
||
$url = $data['data'][0]['url'] ?? null;
|
||
if (!$url) {
|
||
echo "FAIL keine Bild-URL\n";
|
||
$fail++;
|
||
$done++;
|
||
continue;
|
||
}
|
||
$img = @file_get_contents($url);
|
||
if (!$img) {
|
||
echo "FAIL Download fehlgeschlagen\n";
|
||
$fail++;
|
||
$done++;
|
||
continue;
|
||
}
|
||
file_put_contents($out, $img);
|
||
$size = filesize($out);
|
||
echo "OK (" . round($size / 1024) . " KB)\n";
|
||
$ok++;
|
||
$done++;
|
||
@ob_flush(); @flush();
|
||
}
|
||
|
||
echo str_repeat('-', 70) . "\n";
|
||
echo "Fertig: $ok ok · $skip skip · $fail fail\n";
|