from pathlib import Path
import json,html
P=Path(__file__).resolve().parent;D=json.loads((P/'c05-pump-curves.json').read_text())
def start(title,w=1120,h=690):return [f'<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}" role="img" aria-label="{title}"><title>{title}</title><rect width="100%" height="100%" fill="#fbfcfd"/><style>text{{font-family:Arial,sans-serif;fill:#182d3b}}</style>']
def txt(S,x,y,t,size=16):S.append(f'<text x="{x}" y="{y}" font-size="{size}">{html.escape(str(t))}</text>')
def axes(S,x,y,w,h,xlo,xhi,ylo,yhi,xt,yt):
 X=lambda a:x+w*(a-xlo)/(xhi-xlo);Y=lambda a:y+h-h*(a-ylo)/(yhi-ylo)
 for a in xt:S.append(f'<line x1="{X(a)}" y1="{y}" x2="{X(a)}" y2="{y+h}" stroke="#d6e0e5"/>');txt(S,X(a)-10,y+h+23,f'{a:g}',13)
 for a in yt:S.append(f'<line x1="{x}" y1="{Y(a)}" x2="{x+w}" y2="{Y(a)}" stroke="#d6e0e5"/>');txt(S,x-45,Y(a)+4,f'{a:g}',13)
 return X,Y
colors=['#327099','#a94e44','#4f8750'];S=start('Historical pump head trims at 3550rpm');txt(S,35,35,'Pump head trims are specific to one casing and speed',24);X,Y=axes(S,90,110,710,365,0,110,0,250,[0,20,40,60,80,100],[0,50,100,150,200,250]);txt(S,90,83,'Total head, ft',17)
for i,c in enumerate(D['head_trim_curves']):
 S.append('<polyline fill="none" stroke="'+colors[i]+'" stroke-width="2.5" points="'+' '.join(f'{X(q):.2f},{Y(h):.2f}' for q,h in c['samples'])+'"/>')
 for q,h in c['samples']:S.append(f'<circle cx="{X(q)}" cy="{Y(h)}" r="4" fill="{colors[i]}"/>')
 S.append(f'<line x1="814" y1="{140+i*50}" x2="835" y2="{140+i*50}" stroke="{colors[i]}" stroke-width="3"/>');txt(S,840,145+i*50,f'{c["impeller_diameter_in"]:g}-in. impeller',17)
txt(S,320,527,'Flow, US gallons per minute',17);txt(S,90,573,'Historical chart: 1 × 1½ × 7¼ L IN-INI, closed impeller R-3080, 3550 rpm; date April 1965.',16);txt(S,90,607,'Selected trim samples only, estimated ±10 ft head. No shutoff, minimum-flow or speed extrapolation.',16);txt(S,90,641,'A required system head at a flow is a separate input; meeting one head point does not select the pump.',16);S.append('</svg>');(P/'c05-pump-head.svg').write_text('\n'.join(S)+'\n')
S=start('Pump efficiency, calculatedbrakepower and waterNPSH',1120,810);txt(S,35,35,'Efficiency, power and water NPSH use different ordinates',24)
ops=D['maximum_trim_efficiency_and_calculated_power']
for i,(title,ylo,yhi,yt,key) in enumerate([('Efficiency, %',30,60,[30,40,50,60],'efficiency_percent_graphical'),('Calculated brake hp at SG 1',0,10,[0,5,10],'brake_hp_calculated_SG1'),('NPSH — WATER, ft',0,15,[0,5,10,15],None)]):
 x=80+i*365;y=125;X,Y=axes(S,x,y,285,330,40,100,ylo,yhi,[40,60,80,100],yt);txt(S,x,y-35,title,16)
 pts=[(t['Q_USgpm'],t[key]) for t in ops] if key else D['water_NPSH_samples'];S.append('<polyline fill="none" stroke="'+colors[i]+'" stroke-width="2.5" points="'+' '.join(f'{X(q):.2f},{Y(v):.2f}' for q,v in pts)+'"/>')
 for q,v in pts:S.append(f'<circle cx="{X(q)}" cy="{Y(v)}" r="4" fill="{colors[i]}"/>')
 txt(S,x+54,510,'Flow, US gpm',16)
txt(S,80,568,'Maximum 7¼-in. trim at 3550 rpm. Efficiency points: ±3 percentage points; water NPSH: ±1 ft.',16);txt(S,80,605,'Power is calculated: BHP = Q × H × SG / (3960 ηfraction), using graphical head and efficiency.',16);txt(S,80,642,'At 60 US gpm: H ≈ 209 ft, η ≈ 52%, BHP ≈ 6.1 at SG 1, water NPSH ≈ 3.8 ft.',16);txt(S,80,679,'Printed power contours include 3, 5 and 7.5 BHP at SG 1; no full BHP contour family is reconstructed.',16);txt(S,80,716,'Water test temperature is unstated. No hot/viscous-fluid correction or required operating margin is supplied.',16);txt(S,80,753,'Compare NPSH available at the same duty/state against the applicable required criterion plus adopted margin.',16);S.append('</svg>');(P/'c05-pump-performance.svg').write_text('\n'.join(S)+'\n')
