from pathlib import Path
import json,struct,hashlib
root=Path(__file__).resolve().parent
def inspect(name):
 b=(root/name).read_bytes(); assert b[:4]==b'MThd' and b[14:18]==b'MTrk'
 division=int.from_bytes(b[12:14],'big'); end=22+int.from_bytes(b[18:22],'big'); assert end==len(b)
 i=22; tick=0; status=None; tempo=500000; ons=[]; offs=[]
 def vlq():
  nonlocal i
  v=0
  while True:
   n=b[i];i+=1;v=(v<<7)|(n&127)
   if n<128:return v
 while i<end:
  tick+=vlq()
  if b[i]>=128:status=b[i];i+=1
  assert status is not None
  if status==255:
   kind=b[i];i+=1;n=vlq();data=b[i:i+n];i+=n
   if kind==81:tempo=int.from_bytes(data,'big')
   if kind==47:break
  else:
   kind=status&240;n=1 if kind in (192,208) else 2;data=b[i:i+n];i+=n
   if kind==144 and data[1]:ons.append({'pitch':data[0],'tick':tick,'seconds':tick*tempo/1e6/division})
   elif kind==128 or (kind==144 and data[1]==0):offs.append({'pitch':data[0],'tick':tick,'seconds':tick*tempo/1e6/division})
 return {'file':name,'bytes':len(b),'sha256':hashlib.sha256(b).hexdigest(),'noteOns':len(ons),'noteOffs':len(offs),'firstOnsetSeconds':ons[0]['seconds'],'lastOnsetSeconds':ons[-1]['seconds'],'lastReleaseSeconds':offs[-1]['seconds'],'notes':ons}
rows=[inspect('browser-download.mid'),inspect('local-reference.mid')]
assert rows[0]['noteOns']==rows[1]['noteOns']==11
assert rows[0]['noteOffs']==11
assert rows[0]['lastOnsetSeconds']>11.7 and rows[0]['lastReleaseSeconds']>12.5
out={'result':'PASS','browserPreviewCount':11,'intendedSourceNotes':16,'sourceSeconds':12.8,'rows':rows,'sameBytes':rows[0]['sha256']==rows[1]['sha256'],'limitations':'One synthetic input; no other service converted; full endpoint coverage does not mean16 intended notes recovered.'}
(root/'independent-results.json').write_text(json.dumps(out,indent=2),encoding='utf-8')
print(json.dumps({k:v for k,v in out.items() if k!='rows'})); print(json.dumps(rows[0]))
