"""독립이동을 torchNode 로컬(mm) 공간에서 정밀 측정 — 스케일 오독 방지."""
import asyncio, json
from playwright.async_api import async_playwright
URL='http://localhost:8090/DOZIKWORKS_OS_v5_locked.dc.html'
async def main():
    async with async_playwright() as p:
        br=await p.chromium.launch(channel='msedge',headless=True)
        pg=await br.new_page(viewport={'width':1000,'height':700})
        await pg.goto(URL)
        await pg.wait_for_function("window.__dzw && window.__dzw._torchParts", timeout=15000)
        res=await pg.evaluate("""()=>{ const d=window.__dzw, T=d._T; const node=d._torchNode, f=d._torchFlange, b=d._torchBody;
          const toLocal=(o)=>{ const w=new T.Vector3(); o.getWorldPosition(w); return node.worldToLocal(w.clone()); };
          node.updateMatrixWorld(true);
          // 플랜지 +50mm(로컬z) → 몸통 torchNode로컬 이동량(mm)
          const b0=toLocal(b);
          f.position.z+=50; node.updateMatrixWorld(true);
          const b1=toLocal(b);
          const bodyFollow=+b0.distanceTo(b1).toFixed(2);
          f.position.z-=50; node.updateMatrixWorld(true);
          // 몸통 +50mm → 플랜지 torchNode로컬 이동량(mm) 기대 0
          const f0=toLocal(f);
          b.position.z+=50; node.updateMatrixWorld(true);
          const f1=toLocal(f);
          const flangeStay=+f0.distanceTo(f1).toFixed(2);
          b.position.z-=50; node.updateMatrixWorld(true);
          return {bodyFollow_mm:bodyFollow, flangeStay_mm:flangeStay};
        }""")
        print(json.dumps(res,ensure_ascii=False))
        await br.close()
asyncio.run(main())
