import json,struct,io,hashlib
from pathlib import Path
from PIL import Image
p=Path('tideglass-ruin-arch-portal.glb');data=p.read_bytes();l=struct.unpack_from('<I',data,12)[0];g=json.loads(data[20:20+l]);b=data[28+l:];imgs=[]
for im in g['images']:
 v=g['bufferViews'][im['bufferView']];raw=b[v.get('byteOffset',0):v.get('byteOffset',0)+v['byteLength']];image=Image.open(io.BytesIO(raw));assert max(image.size)<=2048
 imgs.append({'name':im.get('name'),'size':image.size,'bytes':len(raw)})
assert len(g['materials'])<=8 and len(data)<12000000
assert not g.get('cameras') and not g.get('animations')
for m in g['materials']:
 assert m.get('normalTexture') and m.get('occlusionTexture') and m['pbrMetallicRoughness'].get('baseColorTexture') and m['pbrMetallicRoughness'].get('metallicRoughnessTexture')
assert len(Path('NOTES.md').read_text().splitlines())==6
n=json.loads(Path('nodes.json').read_text());assert 50000<=n['triangles']<=120000
for f in ['final.png','side.png','clay.png']:assert Image.open(f).size==(1920,1080)
r={'source_sha256':hashlib.sha256(Path('build_tideglass-ruin-arch-portal.py').read_bytes()).hexdigest(),'glb_sha256':hashlib.sha256(data).hexdigest(),'glb_bytes':len(data),'nodes':g['nodes'],'triangles':n['triangles'],'images':imgs,'extensions':g.get('extensionsUsed'),'bbox':n['overall_bounding_box']}
Path('validation.json').write_text(json.dumps(r,indent=2));print(json.dumps(r,indent=2))
