Open-source release: pipeline code, raw logs, derived data, licences, tests

Adds src/ (scripts, raw measurement logs, derived data, report source),
tests/, LICENSE (MIT, code) and LICENSE-DATA.md (CC BY 4.0 for the survey's
data; third-party terms). The report is updated to the current site; the
v1 and v2 data hand-off files are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Toby
2026-10-27 20:09:54 -04:00
parent 75da69fc31
commit c094eb88fa
81 changed files with 249210 additions and 127 deletions
+38
View File
@@ -0,0 +1,38 @@
import { chromium } from 'playwright-core';
import { PAGE, HAND } from './paths.mjs';
const b = await chromium.launch({ executablePath: process.env.CH });
const errs = [], fails = [];
const p = await b.newPage({ viewport: { width: 1440, height: 900 } });
p.on('pageerror', e => errs.push(e.message)); p.on('console', m => { if (m.type() === 'error') errs.push(m.text()) });
await p.goto(PAGE('web/index.html'), { waitUntil: 'load' }); await p.waitForTimeout(2500);
const st = () => p.evaluate(() => ({ view: S.view, k: T[S.view].k, x: T[S.view].x, y: T[S.view].y, rot: globeRot.slice(), fit: FIT[S.view], dis: document.getElementById('treset').disabled }));
const near = (a, b) => Math.abs(a.k / b.k - 1) < .003 && Math.abs(a.x - b.x) < 1.5 && Math.abs(a.y - b.y) < 1.5;
for (const v of ['ae', 'globe', 'dp', 'merc']) {
if (v !== 'ae') { await p.click(`.models button[data-v="${v}"]`); await p.waitForTimeout(1300); }
let s0 = await st();
if (!s0.dis) fails.push(`${v}: Reset enabled on a fresh view`);
await p.click('#tzoom'); await p.waitForTimeout(900);
let s1 = await st();
const changed = !near(s1, s0) || (v === 'globe' && Math.hypot(s1.rot[0] - s0.rot[0], s1.rot[1] - s0.rot[1]) > 1);
if (!changed) fails.push(`${v}: Zoom to route changed nothing`);
if (s1.dis) fails.push(`${v}: Reset still disabled after zooming`);
await p.screenshot({ path: `out/zoom_${v}.png` });
await p.click('#treset'); await p.waitForTimeout(900);
let s2 = await st();
if (!near(s2, s2.fit)) fails.push(`${v}: Reset did not return to the fitted view ${JSON.stringify([s2.k, s2.fit.k])}`);
if (v === 'globe' && Math.hypot(s2.rot[0] + 160, s2.rot[1] - 25) > .5) fails.push(`globe: Reset left rotation at ${s2.rot}`);
if (!s2.dis) fails.push(`${v}: Reset not disabled after resetting`);
console.log(`${v}: zoom k ${s0.k.toFixed(1)} -> ${s1.k.toFixed(1)}, rot ${s0.rot.map(n=>n.toFixed(0))} -> ${s1.rot.map(n=>n.toFixed(0))}; reset -> k ${s2.k.toFixed(1)} rot ${s2.rot.map(n=>n.toFixed(0))}`);
}
// globe: drag, then reset must undo the rotation
await p.click('.models button[data-v="globe"]'); await p.waitForTimeout(1300);
await p.mouse.move(600, 400); await p.mouse.down(); await p.mouse.move(800, 300, { steps: 8 }); await p.mouse.up(); await p.waitForTimeout(100);
let d = await st(); if (d.dis) fails.push('globe: Reset disabled after dragging');
await p.click('#treset'); await p.waitForTimeout(900); d = await st();
if (Math.hypot(d.rot[0] + 160, d.rot[1] - 25) > .5) fails.push(`globe: Reset after drag left rotation ${d.rot}`);
// another route, zoomed on AE
await p.click('.models button[data-v="ae"]'); await p.waitForTimeout(1300);
await p.evaluate(() => { const a = LS.findIndex(s => s.name === 'Fortaleza'), c = LS.findIndex(s => s.name === 'Luanda'); select(LP.find(q => (q.a === a && q.b === c) || (q.a === c && q.b === a)).idx); });
await p.click('#tzoom'); await p.waitForTimeout(900); await p.screenshot({ path: 'out/zoom_ae_sacs.png' });
console.log('FAILS', JSON.stringify(fails)); console.log('ERRORS', JSON.stringify(errs));
await b.close();