import cairosvg,math
W,H=1600,900
PXKM=269.0
EXA=4.0
def px(km):
    return 60+km*PXKM
def py(alt):
    return 640-alt*EXA*PXKM/1000
def txt(x,y,s,size=15,anchor="middle",weight="normal",fill="#111"):
    return f'<text x="{x:.0f}" y="{y:.0f}" font-family="Arial,Helvetica,sans-serif" font-size="{size}" text-anchor="{anchor}" font-weight="{weight}" fill="{fill}">{s}</text>'
def leader(x1,y1,x2,y2):
    return f'<line x1="{x1:.0f}" y1="{y1:.0f}" x2="{x2:.0f}" y2="{y2:.0f}" stroke="#333" stroke-width="1.5"/><circle cx="{x2:.0f}" cy="{y2:.0f}" r="3" fill="#333"/>'
s=[f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" viewBox="0 0 {W} {H}">']
s.append(f'<rect width="{W}" height="{H}" fill="#f6efe2"/>')
k0,k1,k2=0.0,1.4,2.6
pts=[(0,640),(px(1.4),py(0)),(px(2.6),py(300)),(W,py(300)-10),(W,830),(0,830)]
s.append('<polygon points="'+' '.join(f'{x:.0f},{y:.0f}' for x,y in pts)+'" fill="#d8b98a"/>')
pts2=[(0,640),(px(1.4),py(0)),(px(2.6),py(300)),(W,py(300)-10),(W,py(300)+20),(px(2.6)+10,py(300)+30),(px(1.4)+10,py(0)+30),(0,670)]
s.append('<polygon points="'+' '.join(f'{x:.0f},{y:.0f}' for x,y in pts2)+'" fill="#c9a676"/>')
s.append(f'<rect x="0" y="830" width="{W}" height="70" fill="#5a4630"/>')
bx0,bx1=px(0.85),px(1.25)
s.append(f'<rect x="{bx0:.0f}" y="{py(0):.0f}" width="{bx1-bx0:.0f}" height="22" fill="#1b4f7a"/>')
for i in range(6):
    s.append(f'<rect x="{bx0+6+i*17:.0f}" y="{py(0)-4:.0f}" width="13" height="4" fill="#2f6fb5"/>')
s.append(txt((bx0+bx1)/2,py(0)+48,"Bassin bas 800 000 m³, 16 ha",14,"middle","bold"))
s.append(txt((bx0+bx1)/2,py(0)+66,"couvert : PV flottant 75 %, bouclier blanc 20 %",12,"middle"))
hx0,hx1=px(2.7),px(3.1)
s.append(f'<rect x="{hx0:.0f}" y="{py(300)-1:.0f}" width="{hx1-hx0:.0f}" height="22" fill="#1b4f7a"/>')
for i in range(6):
    s.append(f'<rect x="{hx0+6+i*17:.0f}" y="{py(300)-5:.0f}" width="13" height="4" fill="#2f6fb5"/>')
s.append(txt((hx0+hx1)/2-20,py(300)-60,"Bassin haut 800 000 m³, 16 ha, couvert",14,"middle","bold"))
s.append(txt((hx0+hx1)/2-20,py(300)-42,"PV flottant 12 MWc sur chaque bassin",12,"middle"))
s.append(f'<path d="M {hx0:.0f} {py(300)+10:.0f} L {px(1.5):.0f} {py(0)-6:.0f}" stroke="#7fb3d9" stroke-width="10" fill="none"/>')
s.append(f'<path d="M {hx0:.0f} {py(300)+10:.0f} L {px(1.5):.0f} {py(0)-6:.0f}" stroke="#2c3e50" stroke-width="3" fill="none"/>')
s.append(txt(px(1.95)+40,py(150)+70,"Deux conduites DN2000, 300 m de chute sur 1,2 km",14,"middle","bold"))
s.append(leader(px(1.95)+40,py(150)+55,px(2.0),py(150)+6))
ux=px(1.3)
s.append(f'<rect x="{ux:.0f}" y="{py(0)-46:.0f}" width="60" height="46" fill="#6b4f2e"/>')
s.append(txt(ux+30,py(0)-28,"Usine",13,"middle","bold","#fff"))
s.append(txt(ux+30,py(0)-12,"48 / 64 MW",11,"middle","normal","#fff"))
s.append(f'<rect x="{px(0.35):.0f}" y="{py(0)-34:.0f}" width="48" height="34" fill="#777"/>')
s.append(txt(px(0.35)+24,py(0)-14,"Poste",11,"middle","bold","#fff"))
s.append(txt(px(0.35)+24,py(0)+20,"320 MW",12,"middle","bold"))
s.append(f'<line x1="{px(0.35)+48:.0f}" y1="{py(0)-30:.0f}" x2="{ux:.0f}" y2="{py(0)-40:.0f}" stroke="#333" stroke-width="2"/>')
tx0,tx1=px(3.25),px(5.55)
n=34
for i in range(n):
    x=tx0+i*(tx1-tx0)/(n-1)
    g=py(300)-10*(x-px(2.6))/(W-px(2.6))
    s.append(f'<rect x="{x-1:.0f}" y="{g-16:.0f}" width="2" height="16" fill="#555"/>')
    s.append(f'<rect x="{x-10:.0f}" y="{g-20:.0f}" width="20" height="5" fill="#2f6fb5" transform="rotate(-25 {x:.0f} {g-18:.0f})"/>')
s.append(f'<path d="M {tx1:.0f} {py(300)-4:.0f} L {hx1:.0f} {py(300)+2:.0f}" stroke="#5b8fb5" stroke-width="3" fill="none" stroke-dasharray="8,4"/>')
s.append(txt((tx0+tx1)/2,py(300)+70,"Champ de trackers bifaciaux : 500 MWc, environ 7 km², 250 ha de panneaux",16,"middle","bold"))
s.append(txt((tx0+tx1)/2,py(300)+90,"2 100 heures par an, gravier clair ; gouttières sur chaque rangée : la pluie et la rosée descendent au bassin haut",12,"middle"))
s.append(txt((tx0+tx1)/2,py(300)+108,"position rosée la nuit, robots de nettoyage à sec : pas d'eau pour les panneaux",12,"middle"))
s.append(leader((tx0+tx1)/2-300,py(300)+54,(tx0+tx1)/2-300,py(300)-12))
mx=px(5.0)
for j,x in enumerate((px(4.6),px(5.05),px(5.5))):
    g=py(300)-10*(x-px(2.6))/(W-px(2.6))
    h=150*EXA*PXKM/1000
    s.append(f'<rect x="{x-2:.0f}" y="{g-h:.0f}" width="4" height="{h:.0f}" fill="none" stroke="#7a7a7a" stroke-width="1.5" stroke-dasharray="5,3"/>')
    for a in (0,120,240):
        ax=x+60*math.sin(math.radians(a+15*j));ay=g-h-60*math.cos(math.radians(a+15*j))
        s.append(f'<line x1="{x:.0f}" y1="{g-h:.0f}" x2="{ax:.0f}" y2="{ay:.0f}" stroke="#7a7a7a" stroke-width="2" stroke-dasharray="5,3"/>')
s.append(f'<rect x="{px(3.55):.0f}" y="40" width="{px(5.65)-px(3.55):.0f}" height="58" fill="#ffffff" stroke="#7a7a7a" stroke-width="1.5" stroke-dasharray="6,4"/>')
s.append(txt((px(3.55)+px(5.65))/2,62,"Variante mixte, en pointillés : 30 éoliennes de 6 MW (mât de 150 m) et 200 MWc",13,"middle","bold","#444"))
s.append(txt((px(3.55)+px(5.65))/2,82,"1 002 GWh, 441 M€, 30 €/MWh, vend 63 €/MWh au lieu de 49 : elle produit aussi la nuit",12,"middle","normal","#444"))
s.append('<g transform="translate(60,40)">')
s.append('<rect x="0" y="0" width="560" height="150" fill="#ffffff" stroke="#8a6a3e" stroke-width="2"/>')
s.append(txt(280,24,"Hydroloop V14 Soleil : la V14 sans éoliennes",16,"middle","bold","#8a6a3e"))
s.append(txt(15,50,"500 MWc de trackers et 24 MWc flottants à la place des 40 éoliennes",13,"start"))
s.append(txt(15,70,"Bassins, conduites, usine et stockage de 588 MWh de la V14, raccordement 320 MW",13,"start"))
s.append(txt(15,90,"998 GWh par an, 18 % pilotables, 445 M€, 0,45 M€ par GWh annuel",13,"start","bold"))
s.append(txt(15,110,"LCOE 30 €/MWh en privé, 25 en public (V14 éolienne : 28 et 23,5)",13,"start"))
s.append(txt(15,130,"Eau : 640 000 m³ collectés à 250 mm de pluie, 220 000 perdus",13,"start"))
s.append('</g>')
y0=780
s.append(f'<rect x="{px(0.2):.0f}" y="{y0}" width="{PXKM:.0f}" height="10" fill="#fff" stroke="#222" stroke-width="1.5"/>')
s.append(f'<rect x="{px(0.2):.0f}" y="{y0}" width="{PXKM/2:.0f}" height="10" fill="#222"/>')
s.append(txt(px(0.2),y0+28,"0",13,"middle","normal","#222"))
s.append(txt(px(0.7),y0+28,"500 m",13,"middle","normal","#222"))
s.append(txt(px(1.2),y0+28,"1 km",13,"middle","normal","#222"))
vx=30
s.append(f'<line x1="{vx}" y1="{py(0):.0f}" x2="{vx}" y2="{py(300):.0f}" stroke="#222" stroke-width="2"/>')
for a in range(0,301,100):
    s.append(f'<line x1="{vx}" y1="{py(a):.0f}" x2="{vx+10}" y2="{py(a):.0f}" stroke="#222" stroke-width="2"/>')
    s.append(txt(vx+14,py(a)+5,f"{a} m",12,"start"))
s.append(txt(800,885,"Coupe à l'échelle : 1 km horizontal sur la règle du bas, hauteurs exagérées 4 fois (règle de gauche). www.mulo.world, octobre 2026, CC BY 4.0",13,"middle","normal","#efe6d6"))
s.append('</svg>')
cairosvg.svg2png(bytestring='\n'.join(s).encode('utf-8'),write_to='schema_hydroloop_muhleisen_2026_v14_soleil.png',output_width=W,output_height=H)
