from pathlib import Path
import math,csv,json
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
OUT=Path(__file__).resolve().parent
GAMMA=1.4; TA=220.; LIMIT=1600.; CHI=.05
def boundary(e):
    return math.sqrt(2/(GAMMA-1)*((GAMMA+1)/2*LIMIT/TA*(1-CHI*e)/(1-e)-1))
values=[(i/1000,boundary(i/1000)) for i in range(801)]
VISIBLE_SOURCE_END=0.78  # approximate reading from NASA's raster; no point table is published
with (OUT/'nasa2000-figure3.csv').open('w',newline='',encoding='utf-8') as f:
 w=csv.writer(f);w.writerow(['assigned_extraction_ratio','conditional_boundary_Mach']);w.writerows(values)
plt.rcParams.update({'font.size':16,'text.color':'#eff5ff','axes.labelcolor':'#eff5ff','xtick.color':'#eff5ff','ytick.color':'#eff5ff','axes.edgecolor':'#9eb4d5','svg.fonttype':'none'})
fig,ax=plt.subplots(figsize=(10,7),dpi=120,facecolor='#07152b');ax.set_facecolor('#07152b')
x,y=zip(*values)
split=next(i for i,(eta,_) in enumerate(values) if eta >= VISIBLE_SOURCE_END)
ax.plot(x[:split+1],y[:split+1],color='#7be4ff',lw=3)
ax.plot(x[split:],y[split:],color='#7be4ff',lw=3,linestyle=(0,(5,3)))
ax.axvspan(VISIBLE_SOURCE_END,.8,color='#f7c566',alpha=.12,zorder=0)
ax.axvline(VISIBLE_SOURCE_END,color='#f7c566',lw=1.5,linestyle=':',alpha=.9)
ax.set(xlim=(0,.8),ylim=(6,15),xlabel='Generator enthalpy extraction ratio',ylabel='Flight Mach number')
ax.set_xticks([i/10 for i in range(9)]);ax.set_yticks(range(6,16));ax.grid(alpha=.15,color='#aec2e0')
ax.text(.1,11.4,'Supersonic entry required\nby this temperature constraint',fontsize=14)
ax.text(.43,6.65,'Subsonic entry permitted\nby this constraint only',fontsize=14)
fig.suptitle('A temperature constraint, not a flight envelope',fontsize=20,x=.54)
fig.text(.13,.89,'Conditional Eq. (71) reconstruction · NASA 2000 Figure 3 context',fontsize=13)
fig.text(.13,.86,'Dashed tail extends beyond the visible source trace (which ends near η ≈ 0.78).',fontsize=12,color='#f7c566')
fig.text(.13,.015,'T entry limit = 1600 K · T ambient = 220 K · chi = 0.05 · assumed gamma = 1.4',fontsize=12)
fig.subplots_adjust(left=.13,right=.97,bottom=.16,top=.81)
svg_path=OUT/'nasa2000-figure3.svg'
fig.savefig(svg_path,facecolor=fig.get_facecolor());fig.savefig(OUT/'nasa2000-figure3.png',facecolor=fig.get_facecolor());plt.close(fig)
svg_path.write_text('\n'.join(line.rstrip() for line in svg_path.read_text(encoding='utf-8').splitlines())+'\n',encoding='utf-8')
checks=[]
for e,read,allow in [(0,6.3,.2),(.2,7,.2),(.4,8.2,.2),(.6,10.2,.3)]:
 v=boundary(e);checks.append({'extraction':e,'calculated':v,'approximate_visual_reading':read,'visual_allowance':allow,'within_visual_allowance':abs(v-read)<=allow})
assert all(c['within_visual_allowance'] for c in checks)
(OUT/'nasa2000-figure3-methods.json').write_text(json.dumps({'source':'NASA/TP-2000-210387','record':'https://ntrs.nasa.gov/citations/20000095934','locators':'Eq71 physical25/printed19; representative assumptions physical26/printed20; Figure3 physical28/printed22','equation':'Ma_boundary=sqrt((2/(gamma-1))*(((gamma+1)/2)*(T3lim/Ta)*(1-chi*eta)/(1-eta)-1))','inputs':{'T3lim_K':LIMIT,'Ta_K':TA,'chi':CHI,'gamma':GAMMA},'gamma_status':'Explicit reconstruction assumption; numeric value not confirmed in inspected source passages','status':'Conditional equation reconstruction, not exact source curve digitization, author code or measured operating envelope','visible_source_trace_endpoint_eta_approx':VISIBLE_SOURCE_END,'trace_endpoint_status':'Approximate visual reading of the raster curve; no point table is supplied. The dashed segment marks the calculation beyond this visible source trace, not measured or source-tabulated values.','visual_comparison':checks,'limits':['Four loose image-reading checks are not independent model validation or statistical uncertainty.','Visible source trace ends near η≈0.78; model reconstruction continues to η=0.8 as a dashed calculated segment. No equality to an exact source endpoint is claimed.','Only burner-entry temperature/Mach constraint; no thrust, efficiency, stable combustion, electrical feasibility or flight prediction.','Subsonic region meets this constraint only; other physical requirements remain.']},indent=2)+'\n',encoding='utf-8')
print(checks)
