# -*- coding: utf-8 -*-
# 只读本目录合成输入，不联网、不修改设备。
import csv,struct
from pathlib import Path
base=Path(__file__).parent
def string(data,offset):
    end=data.index(b'\0',offset)
    value=data[offset:end].decode('utf-8')
    return value,(end+4)//4*4
def parse_message(data):
    address,p=string(data,0); tags,p=string(data,p); args=[]
    assert tags.startswith(',')
    for tag in tags[1:]:
        if tag=='s': value,p=string(data,p)
        elif tag in ('i','f'):
            value=struct.unpack_from('>'+tag,data,p)[0]; p+=4
        else: raise ValueError('未支持的OSC类型:'+tag)
        args.append(value)
    assert p==len(data)
    return address,args
previous=set(); transitions=[]
for seq in [100,101,102]:
    packet=(base/f'tuio-frame-{seq}.osc').read_bytes()
    assert packet[:8]==b'#bundle\0' and struct.unpack_from('>Q',packet,8)[0]==1
    p=16; messages=[]
    while p<len(packet):
        size=struct.unpack_from('>i',packet,p)[0]; p+=4
        assert size>0 and p+size<=len(packet)
        messages.append(parse_message(packet[p:p+size])); p+=size
    assert p==len(packet)
    assert all(address=='/tuio/2Dcur' for address,args in messages)
    alive=set(str(x) for address,args in messages if args[0]=='alive' for x in args[1:])
    fseq=[args[1] for address,args in messages if args[0]=='fseq']
    assert fseq==[seq]
    set_messages=[args for address,args in messages if args[0]=='set']
    if set_messages:
        assert len(set_messages[0])==7 and set_messages[0][1]==7
        assert abs(set_messages[0][2]-(.2 if seq==100 else .4))<1e-6
    events=['add:'+x for x in sorted(alive-previous)]
    events+=['remove:'+x for x in sorted(previous-alive)]
    events+=['update:'+str(args[1]) for args in set_messages if str(args[1]) in previous and str(args[1]) in alive]
    transitions+=events; previous=alive
assert transitions==['add:7','update:7','remove:7'] and not previous,transitions
print('三个OSC合成二进制束解析通过：',transitions,'；未网络发包。')
