#!/usr/bin/env python3
"""Reproduce the ideal two-body 337 x 398 km example (Python stdlib only)."""
import csv, json, math
from pathlib import Path

OUT = Path(__file__).resolve().parent
R, MU, HP, HA = 6371.0, 398600.435507, 337.0, 398.0
rp, ra = R + HP, R + HA
a, e = (rp + ra) / 2, (ra - rp) / (ra + rp)
period = 2 * math.pi * math.sqrt(a**3 / MU)
rows = []
for deg in range(361):
    nu = math.radians(deg)
    radius = a * (1-e*e) / (1 + e*math.cos(nu))
    speed = math.sqrt(MU * (2/radius - 1/a))
    rows.append({"true_anomaly_deg":deg,"altitude_km":radius-R,"radius_km":radius,"speed_km_s":speed})
with (OUT / "ellipse-337-398.csv").open("w", newline="", encoding="utf-8") as f:
    w=csv.DictWriter(f, fieldnames=rows[0].keys()); w.writeheader(); w.writerows(rows)
result={"model":"Newtonian two-body ellipse around a spherical Earth","earth_radius_km":R,"earth_mu_km3_s2":MU,"perigee_altitude_km":HP,"apogee_altitude_km":HA,"semimajor_axis_km":a,"eccentricity":e,"period_min":period/60,"perigee_speed_km_s":math.sqrt(MU*(2/rp-1/a)),"apogee_speed_km_s":math.sqrt(MU*(2/ra-1/a)),"assumptions":["No atmosphere or drag","No nonspherical gravity, third-body effects, thrust, or relativity","The two altitudes are an unverified scenario input; compatibility is not confirmation of a flight"]}
(OUT / "ellipse-337-398.json").write_text(json.dumps(result,indent=2)+"\n",encoding="utf-8")
# Publication-style altitude versus true anomaly; axes are mapped into this viewBox.
W,H,L,T=900,440,88,40
x=lambda d:L+d/360*(W-L-35)
y=lambda h:T+(H-T-75)*(HA-h)/(HA-HP)
path=" ".join(("M" if i==0 else "L")+f"{x(r['true_anomaly_deg']):.2f},{y(r['altitude_km']):.2f}" for i,r in enumerate(rows))
grid=[]
for d in range(0,361,60):
    xx=x(d); grid += [f'<line x1="{xx:.1f}" y1="{T}" x2="{xx:.1f}" y2="{H-35}" stroke="#d9e0e8"/>',f'<text x="{xx:.1f}" y="{H-8}" text-anchor="middle">{d}°</text>']
for h in (337,352,368,383,398):
    yy=y(h); grid += [f'<line x1="{L}" y1="{yy:.1f}" x2="{W-35}" y2="{yy:.1f}" stroke="#d9e0e8"/>',f'<text x="{L-12}" y="{yy+5:.1f}" text-anchor="end">{h}</text>']
svg=f'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" role="img" aria-labelledby="title desc"><title id="title">Ideal orbital altitude along a reported 337 by 398 kilometre ellipse</title><desc id="desc">The calculated altitude rises smoothly from 337 kilometres at perigee, reaches 398 kilometres at apogee halfway around, then returns to perigee. Horizontal axis is true anomaly, not elapsed time.</desc><rect width="100%" height="100%" fill="#fff"/><g font-family="Arial,sans-serif" font-size="15" fill="#33445a">{''.join(grid)}<text x="{(L+W-35)/2}" y="{H-1}" text-anchor="middle">True anomaly from perigee (degrees)</text><text transform="translate(20 {(T+H-35)/2}) rotate(-90)" text-anchor="middle">Altitude above spherical Earth (km)</text><path d="{path}" fill="none" stroke="#653d98" stroke-width="4"/><circle cx="{x(0)}" cy="{y(HP)}" r="7" fill="#c22c83"/><circle cx="{x(180)}" cy="{y(HA)}" r="7" fill="#c22c83"/><circle cx="{x(360)}" cy="{y(HP)}" r="7" fill="#c22c83"/><text x="{x(0)+10}" y="{y(HP)-12}">Perigee · 337 km</text><text x="{x(180)+10}" y="{y(HA)+22}">Apogee · 398 km</text></g></svg>'''
(OUT / "ellipse-337-398.svg").write_text(svg,encoding="utf-8")
