"""Own packet-arrival ledger; Fraction arithmetic, not an RTP receiver."""
from fractions import Fraction as F
import json
PACKETS=[{'seq':100,'send_ms':0,'arrival_ms':50},{'seq':101,'send_ms':20,'arrival_ms':75},{'seq':102,'send_ms':40,'arrival_ms':115},{'seq':103,'send_ms':60,'arrival_ms':112},{'seq':104,'send_ms':80,'arrival_ms':None},{'seq':105,'send_ms':100,'arrival_ms':155}]
def demo():
    arrivals=sorted((p for p in PACKETS if p['arrival_ms'] is not None),key=lambda p:p['arrival_ms'])
    jitter=F(0);previous=None;trace=[]
    for p in arrivals:
        transit=F(8*(p['arrival_ms']-p['send_ms']))
        d=None if previous is None else transit-previous
        if d is not None:jitter+=(abs(d)-jitter)/16
        trace.append({'seq':p['seq'],'arrival_ms':p['arrival_ms'],'transit_ticks':str(transit),'spacing_difference_ticks':None if d is None else str(d),'J_ticks':str(jitter),'J_ms':float(jitter/8)})
        previous=transit
    schedules=[]
    for delay in [60,80]:
        rows=[{**p,'playout_deadline_ms':p['send_ms']+delay,'state':'missing' if p['arrival_ms'] is None else 'late' if p['arrival_ms']>p['send_ms']+delay else 'on_time'} for p in PACKETS]
        counts={s:sum(r['state']==s for r in rows) for s in ['on_time','late','missing']};schedules.append({'authored_delay_ms':delay,'rows':rows,'counts':counts})
    assert [p['seq'] for p in arrivals]==[100,101,103,102,105]
    assert schedules[0]['counts']=={'on_time':4,'late':1,'missing':1} and schedules[1]['counts']=={'on_time':5,'late':0,'missing':1}
    unique={p['seq'] for p in arrivals};expected=max(unique)-min(unique)+1;loss=expected-len(unique);assert loss==1
    return {'RTP_clock_ticks_per_second':8000,'authored_packet_ledger':PACKETS,'arrival_order_jitter':trace,'playout_schedules':schedules,'sequence_range_expected':expected,'unique_packets_received_including_late':len(unique),'missing_in_observed_range':loss,'tail_beyond_last_received_known':False,'jitter_buffer_or_network_or_PLC_executed':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
