import csv, math
BART=[("Embarcadero",37.7929,-122.3968),("Montgomery St",37.7894,-122.4013),
("Powell St",37.7844,-122.4079),("Civic Center / UN Plaza",37.7796,-122.4137),
("16th St Mission",37.7650,-122.4197),("24th St Mission",37.7522,-122.4184),
("Glen Park",37.7332,-122.4335),("Balboa Park",37.7215,-122.4475)]
rows=[];bad=0
for ln in open('muni_raw.txt'):
    ln=ln.rstrip('\n')
    if not ln: continue
    p=ln.split('|')
    if len(p)!=3: bad+=1; continue
    n,la,lo=p[0],float(p[1]),float(p[2])
    if -122.52<=lo<=-122.35 and 37.70<=la<=37.84:
        rows.append(('muni','',n,la,lo))
for n,la,lo in BART: rows.append(('bart','',n+' (BART)',la,lo))
with open('transit_stops.csv','w',newline='') as f:
    w=csv.writer(f); w.writerow(['mode','route','name','lat','lon']); w.writerows(rows)
print("raw lines parsed bad:",bad,"total rows:",len(rows))
from collections import Counter
print("by mode:",Counter(r[0] for r in rows))
def hav(a,b,c,d):
    R=6371000;p=math.radians;dla=p(c-a);dlo=p(d-b)
    x=math.sin(dla/2)**2+math.cos(p(a))*math.cos(p(c))*math.sin(dlo/2)**2
    return 2*R*math.asin(math.sqrt(x))
pts=[(r[3],r[4]) for r in rows]
# Powell St 200m
n1=sum(1 for la,lo in pts if hav(la,lo,37.7844,-122.4079)<=200)
print("PASS" if n1>=1 else "FAIL","stops within 200m of Powell St station:",n1)
def seg_dist(pla,plo,a,b,c,d):
    # approx planar in meters
    kx=111320*math.cos(math.radians(37.78)); ky=110540
    px,py=(plo-b)*kx,(pla-a)*ky
    vx,vy=(d-b)*kx,(c-a)*ky
    L2=vx*vx+vy*vy
    t=max(0,min(1,(px*vx+py*vy)/L2))
    dx,dy=px-t*vx,py-t*vy
    return math.hypot(dx,dy)
n2=sum(1 for la,lo in pts if seg_dist(la,lo,37.7815,-122.4900,37.7865,-122.4200)<=150)
print("PASS" if n2>=15 else "FAIL","stops within 150m of Geary line:",n2)
n3=sum(1 for la,lo in pts if -122.5060<=lo<=-122.4620 and abs(la-37.7615)*110540<=150)
print("PASS" if n3>=10 else "FAIL","stops within 150m of Judah St:",n3)
