Add AC/BC RTCP programs and 3D machine manager

This commit is contained in:
2026-09-20 12:31:12 +08:00
parent 1c1e5f9672
commit 8aab531b02
363 changed files with 53213 additions and 58 deletions

View File

@@ -0,0 +1,27 @@
import assert from 'node:assert/strict';
import { mkdir, writeFile } from 'node:fs/promises';
import { fileURLToPath, pathToFileURL } from 'node:url';
const { chromium } = await import(pathToFileURL(process.env.PLAYWRIGHT_MODULE).href);
const directory = new URL('../docs/teaching/rtcp-beginners/', import.meta.url);
await mkdir(new URL('verification/',directory),{recursive:true});
const browser = await chromium.launch({executablePath:'/usr/bin/google-chrome',headless:true,args:['--no-sandbox']});
try {
const page = await browser.newPage({viewport:{width:794,height:1123}});
const errors=[];page.on('pageerror',(e)=>errors.push(e.message));
await page.goto(new URL('handbook.html',directory).href);await page.emulateMedia({media:'print'});
await page.evaluate(async()=>{await document.fonts.ready;await Promise.all([...document.images].map((im)=>im.decode()));});
const checks=await page.locator('.sheet').evaluateAll((pages)=>pages.map((sheet)=>{
const outer=sheet.getBoundingClientRect(),body=sheet.querySelector('.body'),key=sheet.querySelector('.key').getBoundingClientRect();
const violations=[...body.querySelectorAll('p,li,table,figure,pre,.equation,aside,h2')].filter((e)=>{
const r=e.getBoundingClientRect();return r.bottom>key.top-6||r.right>outer.right-32||r.left<outer.left+28;
}).map((e)=>({tag:e.tagName,text:e.textContent.slice(0,70),bottom:e.getBoundingClientRect().bottom-outer.top}));
const title=sheet.querySelector('h1');const range=document.createRange();range.selectNodeContents(title);
return {page:Number(sheet.dataset.page),title:title.textContent,violations,overflow:body.scrollHeight>body.clientHeight+1,title_right:range.getBoundingClientRect().right-outer.left,images:[...sheet.querySelectorAll('img')].map((im)=>({src:im.getAttribute('src'),loaded:im.complete&&im.naturalWidth>0})),characters:body.innerText.length};
}));
await writeFile(new URL('verification/layout.json',directory),JSON.stringify({report_id:'rtcp-beginners-layout-v1',pages:checks,errors},null,2)+'\n');
for(const check of checks) await page.locator(`.sheet[data-page="${check.page}"]`).screenshot({path:fileURLToPath(new URL(`verification/page-${String(check.page).padStart(2,'0')}.png`,directory))});
const bad=checks.filter((c)=>c.violations.length||c.overflow||c.title_right>760||c.images.some((im)=>!im.loaded));
assert.deepEqual(errors,[]);assert.deepEqual(bad,[],'Handbook page overflow');
await page.pdf({path:fileURLToPath(new URL('五轴RTCP与工件坐标-初学者完整讲义.pdf',directory)),preferCSSPageSize:true,printBackground:true,tagged:true,outline:true});
console.log(JSON.stringify({report_id:'rtcp-beginners-layout-v1',status:'verified',pages:checks.length}));
} finally {await browser.close();}