import cairosvg,math
W,H=1600,900
def txt(x,y,s,size=16,anchor="middle",weight="normal",fill="#111"):
    return f'<text x="{x}" y="{y}" 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}" y1="{y1}" x2="{x2}" y2="{y2}" stroke="#333" stroke-width="1.5"/><circle cx="{x2}" cy="{y2}" r="3" fill="#333"/>'
def vagues(x,y,w,n,col="#a8c4dc"):
    return "".join(f'<path d="M {x+i*w/n} {y} q {w/n/4} -6 {w/n/2} 0 q {w/n/4} 6 {w/n/2} 0" stroke="{col}" stroke-width="2" fill="none"/>' for i in range(n))
def eolienne(x,y,h,r):
    s=[f'<rect x="{x-2}" y="{y}" width="4" height="{h}" fill="#444"/>',f'<circle cx="{x}" cy="{y}" r="3" fill="#333"/>']
    for a in (0,120,240):
        ax=x+r*math.sin(math.radians(a));ay=y-r*math.cos(math.radians(a))
        s.append(f'<line x1="{x}" y1="{y}" x2="{ax:.0f}" y2="{ay:.0f}" stroke="#333" stroke-width="2.5"/>')
    return "".join(s)
def dessin(gold):
    taille={1:1,2:2,3:3,4:1}[gold]
    s=[f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" viewBox="0 0 {W} {H}">',f'<rect width="{W}" height="{H}" fill="#eef3f7"/>']
    mer=(taille==3)
    s.append('<polygon points="0,700 480,700 700,260 900,180 1150,120 1600,100 1600,830 0,830" fill="#a89a7c"/>')
    s.append('<polygon points="900,180 1150,120 1600,100 1600,140 1160,160 910,215" fill="#7f9a6a"/>')
    s.append('<polygon points="480,700 700,260 735,262 520,700" fill="#8c7b5c"/>')
    if mer:
        s.append('<rect x="0" y="700" width="480" height="130" fill="#3b7fb5"/>')
        s.append(vagues(10,720,460,10,"#9fc3e0"))
        s.append(txt(240,790,"La mer : bassin bas de la boucle salée, et jamais un village sous le lac",13,"middle","bold","#fff"))
    else:
        s.append('<polygon points="0,700 480,700 520,700 520,730 0,730" fill="#b5c49f"/>')
    s.append('<rect x="0" y="830" width="1600" height="70" fill="#17415f"/>')
    for i in range(12):
        x=960+i*50
        s.append(f'<line x1="{x}" y1="{145-i*2}" x2="{x+8}" y2="{125-i*2}" stroke="#2f6fb5" stroke-width="2" stroke-dasharray="3,3"/>')
    s.append('<path d="M 930 178 L 1590 108" stroke="#2c7fb8" stroke-width="5" fill="none"/>')
    s.append(txt(1260,80,"L'impluvium Pacha : la montagne reliée au lac par un canal de ceinture de 20 à 45 km",14,"middle","bold"))
    s.append(txt(1260,98,"7 km² captés par kilomètre, 0,5 M€ le kilomètre, remboursé en un à deux ans : le levier qui fait baisser le kWh",12,"middle"))
    s.append('<ellipse cx="1080" cy="235" rx="150" ry="38" fill="#1b4f7a" stroke="#0a3d62" stroke-width="2"/>')
    s.append(vagues(950,235,260,8))
    s.append('<rect x="925" y="222" width="12" height="40" fill="#8a6a3e"/>')
    s.append(txt(1210,300,"Bassin 3 : le lac de pluie, 5 à 15 fois le bassin haut",14,"middle","bold"))
    s.append(txt(1210,318,{1:"2 millions de m³ (3 en mousson), digue en argile compactée, décantation",2:"8 millions de m³ (12 en mousson), digue en argile compactée, décantation",3:"4 millions de m³ d'eau douce (12 en mousson), au-dessus de la mer, pas d'un village"}[taille],12,"middle"))
    s.append('<path d="M 940 262 L 940 330 L 860 330" stroke="#5b8fb5" stroke-width="5" fill="none"/>')
    s.append('<rect x="730" y="330" width="130" height="18" rx="4" fill="#8a6a3e"/>')
    s.append(txt(722,318,"Le lac remplit le bassin haut en premier,",11,"end"))
    s.append(txt(722,333,"les pompes complètent",11,"end"))
    if taille==3:
        s.append('<rect x="600" y="350" width="230" height="45" fill="#1b4f7a" stroke="#0a3d62" stroke-width="2"/>')
        s.append('<rect x="713" y="350" width="4" height="45" fill="#d8cdb4"/>')
        s.append(vagues(605,372,105,3));s.append(vagues(720,372,105,3,"#c8e0b0"))
        s.append(txt(845,378,"Bassin haut en deux cellules, 2 × 400 000 m³ : douce (pluie) et salée (boucle de mer)",12,"start","bold"))
    else:
        s.append('<rect x="600" y="350" width="230" height="45" fill="#1b4f7a" stroke="#0a3d62" stroke-width="2"/>')
        s.append(vagues(605,372,220,6))
        s.append(txt(845,378,{1:"Bassin haut 200 000 m³, revêtu, marnage quotidien",2:"Bassin haut 800 000 m³, revêtu, marnage quotidien"}[taille],12,"start","bold"))
    for i in range(4 if taille==1 else 8):
        x=1200+i*(60 if taille==1 else 45)
        s.append(eolienne(x,132-i*3,50,18))
    s.append(txt(1240,440,{1:"10 éoliennes de 6 MW et 16 MWc de trackers : la V11 fait le kWh",2:"40 éoliennes de 6 MW, mâts de 150 m, 16 MWc : la V14 fait le kWh",3:"10 éoliennes, 100 MWc et 1 000 panneaux hybrides : la V15 complète"}[taille],13,"middle","bold"))
    s.append(txt(1240,458,"Quand le lac a de l'eau, les pompes dorment et tout le vent se vend en direct",12,"middle"))
    s.append('<path d="M 640 395 L 520 700 L 440 700" stroke="#7fb3d9" stroke-width="9" fill="none"/>')
    s.append('<path d="M 640 395 L 520 700 L 440 700" stroke="#2c3e50" stroke-width="3" fill="none"/>')
    s.append(txt(640,662,{1:"Conduite 300 m, Pelton 12 MW, pompes 16 MW, Pelton de pluie 4,3 MW",2:"Deux DN2000, 300 m, Pelton 48 MW, pompes 64 MW, Pelton de pluie 2 × 4,5 MW à 45 km de canal",3:"Puits blindé 1 500 m, Pelton 300 MW en duplex : 180 MW hors pointe sur la pluie"}[taille],14,"start","bold"))
    s.append(leader(636,657,572,600))
    s.append('<rect x="270" y="645" width="200" height="90" fill="#5a4024"/>')
    s.append('<rect x="315" y="630" width="110" height="20" fill="#8a6a3e"/>')
    s.append(txt(370,675,"Usine",13,"middle","bold","#fff"))
    s.append(txt(370,698,"pointe : grande Pelton, eau du lac d'abord",10,"middle","normal","#fff"))
    s.append(txt(370,716,"jour et nuit : la grande Pelton sur la pluie" if taille==3 else "jour et nuit : Pelton de pluie sur l'excédent",10,"middle","normal","#fff"))
    if taille==3:
        s.append('<rect x="30" y="600" width="250" height="40" fill="#1b4f7a" stroke="#0a3d62" stroke-width="2"/>')
        s.append(vagues(35,620,240,6,"#c8e0b0"))
        s.append(txt(155,660,"Bassin bas douce : l'eau de la ville, par gravité",12,"middle","bold"))
        s.append('<line x1="300" y1="690" x2="280" y2="620" stroke="#5b8fb5" stroke-width="5"/>')
        s.append('<rect x="40" y="520" width="40" height="60" fill="#c3ccd6" stroke="#9aa6b2"/>')
        s.append('<rect x="100" y="530" width="40" height="50" fill="#c3ccd6" stroke="#9aa6b2"/>')
        s.append(txt(155,495,"La ville côtière : 200 millions de m³",11,"middle","bold"))
        s.append(txt(155,510,"d'eau douce par an, sans dessalement",11,"middle","bold"))
    else:
        s.append('<rect x="40" y="745" width="400" height="55" fill="#1b4f7a" stroke="#0a3d62" stroke-width="2"/>')
        s.append(vagues(45,772,390,10))
        s.append(txt(240,818,{1:"Bassin bas 200 000 m³, berges revêtues",2:"Bassin bas 800 000 m³, berges revêtues"}[taille],13,"middle","bold"))
        s.append('<line x1="300" y1="730" x2="300" y2="745" stroke="#5b8fb5" stroke-width="6"/>')
        s.append('<path d="M 40 772 L 0 772" stroke="#5b8fb5" stroke-width="6"/>')
        s.append(txt(135,650,"Ruisseau régulé vers la vallée :",12,"middle","bold"))
        s.append(txt(135,668,"l'eau de pluie turbinée ressort en bas,",12,"middle"))
        s.append(txt(135,686,"toute l'année, pour les villages et les champs",12,"middle"))
        s.append(leader(120,695,30,765))
    if gold in (1,2,3):
        s.append('<path d="M 1600 300 L 1480 300 L 1380 262 L 1240 262" stroke="#2c7fb8" stroke-width="7" fill="none" stroke-dasharray="14,8"/>')
        s.append('<path d="M 1600 300 L 1480 300" stroke="#1b4f7a" stroke-width="11" fill="none"/>')
        s.append(txt(1420,335,"Cours d\'eau détourné hors du bassin du canal, 0,3 à 10 m³/s",12,"middle","bold","#17415f"))
        s.append(txt(1420,352,"par tunnel ou canal depuis la vallée voisine : jour et nuit, sécheresse comprise",11,"middle"))
        s.append('<path d="M 700 455 q 30 -20 60 0 q 30 20 60 0" stroke="#2c7fb8" stroke-width="4" fill="none"/>')
        s.append('<path d="M 820 455 L 980 262" stroke="#5b8fb5" stroke-width="3" fill="none" stroke-dasharray="5,4"/>')
        s.append(txt(700,478,"Ruisseau sous le canal : bélier hydraulique (7 à 8 % du débit remonté sans énergie)",11,"start"))
        s.append(txt(700,494,"ou pompe sur le surplus de la centrale (30 m de relevage : 14 % de l\'énergie rendue à 300 m)",11,"start"))
    else:
        s.append('<rect x="1420" y="165" width="160" height="55" fill="#dcd3c2" stroke="#8a6a3e" stroke-width="2"/>')
        s.append('<path d="M 1420 220 L 1580 220" stroke="#6b4f2a" stroke-width="5"/>')
        s.append('<path d="M 1430 222 q 10 20 0 40 M 1460 222 q 10 20 0 40" stroke="#2c7fb8" stroke-width="4" fill="none"/>')
        s.append('<path d="M 1445 258 L 1445 275 L 1240 275 L 1240 262" stroke="#2c7fb8" stroke-width="7" fill="none"/>')
        s.append(txt(1460,140,"Massif karstique ou volcanique",12,"middle","bold","#17415f"))
        s.append(txt(1460,155,"la source sort au contact de la couche imperméable",11,"middle"))
        s.append(txt(1500,187,"calcaire ou basalte : l\'eau descend",10,"middle"))
        s.append(txt(1500,203,"couche imperméable : la source",10,"middle"))
        s.append(txt(1420,335,"Source captée par gravité, 1 à 10 m³/s, constante, eau claire",12,"middle","bold","#17415f"))
        s.append(txt(1420,352,"Francis réversibles possibles, pas de canal de dérivation",11,"middle"))
    s.append('<g transform="translate(1040,480)">')
    s.append('<rect x="0" y="0" width="520" height="150" fill="#ffffff" stroke="#17415f" stroke-width="2"/>')
    s.append(txt(260,24,{1:"V17 Gold 1 : la Pacha 1 plus un ruisseau pérenne",2:"V17 Gold 2 : la Pacha 2 complète plus une petite rivière",3:"V17 Gold 3 : la Pacha 3 plus un torrent de montagne",4:"V17 Gold 4 : une Pacha plus une grande source"}[gold],15,"middle","bold","#17415f"))
    lignes={1:["Ruisseau de 1 m³/s détourné vers le lac : 31 millions de m³ par an, 23 GWh à 300 m","335 GWh au lieu de 312 : 28,1 €/MWh au lieu de 29,4 ; 3 m³/s : 380 GWh à 25,9","Lac jamais vide (39 jours par an sans lui), pompes 1 GWh au lieu de 32","Dérivation 3 à 10 M€ ; forage écarté : 50 L/s relevés de 100 m, +1 GWh","112 millions de m³ rendus à la vallée, débit réservé laissé au ruisseau"],2:["Petite rivière de 3 à 10 m³/s : 95 à 315 millions de m³ par an","1 247 GWh à 23,1 €/MWh avec 3 m³/s, 1 406 à 21,8 avec 10, au lieu de 1 180 à 23,6","Pelton de pluie de 17 à 35 MW, deux unités, qui tourne jour et nuit","Dérivation 5 à 25 M€ (tunnel à travers la crête compris)","359 à 573 millions de m³ régulés vers la vallée"],3:["Torrent de 3 m³/s à 1 500 m : chaque m³ vaut 3,7 kWh","+175 GWh vendus et 210 GWh de surplus en moins à acheter : +17 M€ par an","Torrent de fonte (maximum en juin) : +196 GWh, +18 M€ par an","Un tunnel de 10 km (50 M€) se paie encore ; 10 m³/s : 2 155 GWh","Lac vide 20 jours au lieu de 125, eau douce rendue à la côte"],4:["Source karstique ou volcanique de 1 à 10 m³/s, débit constant","Pacha 1 + 1 m³/s : 27,9 €/MWh ; Pacha 2 + 10 : 21,5 ; Pacha 3 + 5 : +29 M€ par an","Eau claire : Francis réversibles possibles, 0,5 €/MWh de moins","Captage et conduite 1,5 à 6 M€, pas de canal de dérivation","Le lac se pose sur la couche imperméable, sous le karst, là où sort la source"]}[gold]
    for i,l in enumerate(lignes):
        s.append(txt(15,52+i*20,l,12,"start","bold" if i==1 else "normal"))
    s.append('</g>')
    titres={1:"Hydroloop Muhleisen 2026 V17 Gold 1 : la Pacha 1 plus un ruisseau pérenne, 335 GWh à 28,1 €/MWh, un lac qui ne se vide plus",2:"Hydroloop Muhleisen 2026 V17 Gold 2 : la Pacha 2 complète plus une petite rivière, 1 247 à 1 406 GWh à 23,1 et 21,8 €/MWh",3:"Hydroloop Muhleisen 2026 V17 Gold 3 : la Pacha 3 plus un torrent de montagne turbiné à 1 500 m, +17 à +18 M€ par an",4:"Hydroloop Muhleisen 2026 V17 Gold 4 : une Pacha plus une grande source, l\'eau constante et claire du karst ou du volcan"}
    s.append(txt(800,860,titres[gold],21,"middle","bold","#fff"))
    s.append(txt(800,885,"Coupe schématique, pas à l'échelle. Gold : l'eau gratuite qui s'ajoute à la pluie. www.mulo.world, octobre 2026, CC BY 4.0",13,"middle","normal","#dfe7ee"))
    s.append('</svg>')
    return "\n".join(s)
for g in (1,2,3,4):
    cairosvg.svg2png(bytestring=dessin(g).encode("utf-8"),write_to=f"schema_hydroloop_muhleisen_2026_v17_gold_{g}.png",output_width=W,output_height=H)
print("ok")
