/ concept-collection / turing-surface
Sign in
concept-collection / turing-surface
57 lines · 2.4 KBCodeBlameHistory
0af3386Reaction-diffusion on spherical-harmonic surfacesJeremy Magland 1/** Screenshot the demo page (dist/) in headless Chrome. Usage: node scripts/screenshot.mjs out.png [light|dark] */
2import { createServer } from 'node:http';
3import { readFile } from 'node:fs/promises';
4import { extname, join } from 'node:path';
5import puppeteer from 'puppeteer-core';
7const out = process.argv[2] ?? 'demo.png';
8const scheme = process.argv[3] ?? 'light';
9const minSteps = Number(process.argv[4] ?? 200);
10const DIST = new URL('../dist/', import.meta.url).pathname;
11const MIME = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css' };
13const server = createServer(async (req, res) => {
14 try {
15 const path = req.url === '/' ? '/index.html' : req.url.split('?')[0];
16 const data = await readFile(join(DIST, path));
17 res.writeHead(200, { 'content-type': MIME[extname(path)] ?? 'application/octet-stream' });
18 res.end(data);
19 } catch {
20 res.writeHead(404);
21 res.end();
22 }
23});
24await new Promise((r) => server.listen(0, '127.0.0.1', r));
25const port = server.address().port;
27const browser = await puppeteer.launch({
28 executablePath: process.env.CHROME_PATH ?? '/usr/bin/google-chrome',
29 args: ['--headless=new', '--no-sandbox', '--enable-unsafe-webgpu',
30 '--use-webgpu-adapter=swiftshader', '--enable-unsafe-swiftshader'],
31});
32const page = await browser.newPage();
33await page.setViewport({ width: 1000, height: 900 });
34await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: scheme }]);
35page.on('console', (m) => console.log(' [page]', m.text()));
36await page.goto(`http://127.0.0.1:${port}/index.html`, { waitUntil: 'load' });
37// the sim starts paused; wait for setup to finish, then press Run
38await page.waitForFunction(() => /grid/.test(document.getElementById('stats')?.textContent ?? ''), { timeout: 120_000 });
39await page.click('#runpause');
40await page.waitForFunction(
41 (min) => {
42 const s = document.getElementById('stats');
43 const e = document.getElementById('err');
44 const m = s && s.textContent.match(/\((\d+) steps\)/);
45 return (m && Number(m[1]) >= min) || (e && e.textContent.length > 4);
46 },
47 { timeout: 600_000 },
48 minSteps,
49);
50await new Promise((r) => setTimeout(r, 300));
51await page.screenshot({ path: out });
52console.log('screenshot:', out);
53console.log('stats:', await page.$eval('#stats', (el) => el.textContent));
54const err = await page.$eval('#err', (el) => el.textContent);
55if (err) console.log('err:', err);
56await browser.close();
57server.close();
moveopenescclose