Files
HiveGrid-Marketing/webinar/slides/waben.py
T
dejanandClaude Opus 5.5 686ee36b4f HiveGrid Marketing: Hub mit Strategie, Redaktionsplan, Dashboard, Produktionsvorgaben und Webinar
Stand 16.10.2026. Enthält das Marketing-Dashboard, die Daten in daten/,
die Produktionsvorgaben, Reels und das Webinar mit Skript, Sprechzettel
und Präsentation (HTML, PowerPoint, PDF).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:09:07 +02:00

88 lines
3.6 KiB
Python

"""Wabenmuster für Slide 2 (noah) und Slide 3 (problem).
Aufruf: python3 waben.py <Ordner mit den Slide-Dateien>, zum Beispiel quelle/slides.
Ein Raster für beide Slides. Auf Slide 2 liegt es um Noahs Foto und läuft
unten bündig aus der Slide heraus. Slide 3 setzt dieselben Reihen oben fort
(y minus 1080) und blendet nach unten aus. Die Reihe auf y = 1080 wird von
der Kante halbiert: obere Hälfte auf Slide 2, untere auf Slide 3.
"""
import math, re, sys
from pathlib import Path
P = Path(sys.argv[1])
X0, W = 960, 960
R = 45
DX, DY = math.sqrt(3) * R, 1.5 * R
RAHMEN = (1164, 199, 1716, 881) # Foto-Rahmen auf Slide 2
MX, MY = 1440, 540
SEITLICH = 175 # Ausblenden nach links und rechts
UNTEN3 = 330 # Ausblenden nach unten auf Slide 3
def seitlich(x):
l, r = RAHMEN[0], RAHMEN[2]
d = max(l - x, 0, x - r)
return max(0.0, 1 - d / SEITLICH)
def stark(op):
return op ** 1.4
def punkte(x, y):
return " ".join(f"{x - X0 + R * math.cos(math.radians(a)):.1f},{y + R * math.sin(math.radians(a)):.1f}"
for a in (-90, -30, 30, 90, 150, 210))
def zelle(x, y, op, gelb=False):
if gelb:
return f'<polygon points="{punkte(x, y)}" fill="#F1B729"/>'
return (f'<polygon points="{punkte(x, y)}" fill="#FFFFFF" fill-opacity="{op:.2f}" '
f'stroke="#D6D6D9" stroke-opacity="{op:.2f}" stroke-width="1.5"/>')
def raster():
for j in range(-10, 14):
for i in range(-8, 9):
yield MX + i * DX + (DX / 2 if j % 2 else 0), MY + j * DY
# Slide 2: Abstand zum Rahmen, der nach unten bis über die Kante verlängert ist.
def slide2():
l, o, r, u = RAHMEN
zellen = []
for x, y in raster():
if not (X0 - R < x < X0 + W + R and -R < y < 1080 + R): continue
if l <= x <= r and o <= y <= u: continue # hinter dem Foto
d = math.hypot(max(l - x, 0, x - r), max(o - y, 0))
op = stark(max(0.0, 1 - d / SEITLICH))
if op >= 0.04: zellen.append((x, y, d, op))
def naechste(zx, zy):
return min((z for z in zellen if 20 < z[2] < 90 or (z[1] > u and z[2] < 5)),
key=lambda z: math.hypot(z[0] - zx, z[1] - zy))
gelb = {naechste(1120, 300)[:2], naechste(1770, 560)[:2], naechste(1250, 945)[:2]}
return "".join(zelle(x, y, op, (x, y) in gelb) for x, y, d, op in zellen), 1080
# Slide 3: dieselben Spalten, Reihen um 1080 nach oben verschoben.
def slide3():
teile = []
for x, y in raster():
y3 = y - 1080
if not (X0 - R < x < X0 + W + R and -R < y3 < UNTEN3 + R): continue
op = stark(seitlich(x) * max(0.0, 1 - max(y3, 0) / UNTEN3))
if op >= 0.04: teile.append(zelle(x, y3, op))
return "".join(teile), UNTEN3 + R
def einsetzen(datei, svg_inhalt, hoehe, vor):
s = (P / datei).read_text()
s = re.sub(r'<svg aria-label="" data-waben="1".*?</svg>\n', "", s, flags=re.S)
s = re.sub(r'<svg aria-label="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 1080".*?</svg>\n', "", s, flags=re.S)
svg = (f'<svg aria-label="" data-waben="1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {hoehe}" width="{W}" height="{hoehe}" '
f'style="position:absolute;left:{X0}px;top:0px;width:{W}px;height:{hoehe}px">{svg_inhalt}</svg>\n')
i = s.index(vor)
s = s[:i] + svg + s[i:]
(P / datei).write_text(s)
inhalt, h = slide2()
einsetzen("noah.html", inhalt, h, '<svg aria-label="Rahmen um das Foto"')
inhalt, h = slide3()
s = (P / "problem.html").read_text()
erstes_kind = s.index(">", s.index("<section")) + 2 # direkt nach dem Section-Tag
einsetzen("problem.html", inhalt, h, s[erstes_kind:erstes_kind + 40])
print("ok")