From 09cd3cbf71516dc6b51258caf9903c57f27fc166 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:08:26 +0000 Subject: [PATCH 1/2] Initial plan From f8fc16b7a7136a879cc86459467bca536f273625 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:14:24 +0000 Subject: [PATCH 2/2] Fix setDemoControls to interact with actual demo UI (radio buttons + range slider) Co-authored-by: mnm-matin <45293386+mnm-matin@users.noreply.github.com> --- package-lock.json | 5 +- src/benchmarks/run-demo-interaction-bench.ts | 65 ++++++++++++++++---- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 65d0de6..ce76362 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { - "name": "viz-lab", + "name": "hyper-scatter", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "viz-lab", + "name": "hyper-scatter", "version": "0.1.0", + "license": "MIT", "devDependencies": { "@types/node": "^20.10.0", "puppeteer": "^24.34.0", diff --git a/src/benchmarks/run-demo-interaction-bench.ts b/src/benchmarks/run-demo-interaction-bench.ts index cf1521e..dadc7f3 100644 --- a/src/benchmarks/run-demo-interaction-bench.ts +++ b/src/benchmarks/run-demo-interaction-bench.ts @@ -217,26 +217,69 @@ async function installFpsProbe(page: Page): Promise { } async function setDemoControls(page: Page, cfg: Config): Promise { - // Select renderer/geometry/points. - await page.select('#renderer', 'webgl'); - await page.select('#geometry', cfg.geometry); - await page.select('#numPoints', String(cfg.points)); + // The demo page (index.html / app.ts) uses: + // - Radio buttons: input[name="geometry"] (values: 'euclidean' | 'poincare') + // - Radio buttons: input[name="renderer"] (values: 'webgl' | 'reference') + // - Range slider: input#numPoints (0–10, mapped to POINT_PRESETS) + // There is no explicit "Generate" button; the app auto-generates on input changes. + + // POINT_PRESETS from app.ts — kept in sync so we can map a point count to a slider index. + const POINT_PRESETS = [ + 1_000, 10_000, 50_000, 100_000, 250_000, 500_000, + 1_000_000, 2_000_000, 5_000_000, 10_000_000, 20_000_000, + ]; + + // Snap to the nearest preset. + const sliderIndex = POINT_PRESETS.reduce( + (best, v, i) => + Math.abs(v - cfg.points) < Math.abs(POINT_PRESETS[best] - cfg.points) ? i : best, + 0, + ); + const actualPoints = POINT_PRESETS[sliderIndex]; + + // Select geometry via its radio button. + await page.evaluate((geometry: string) => { + const el = document.querySelector( + `input[name="geometry"][value="${geometry}"]`, + ); + if (el) { + el.checked = true; + el.dispatchEvent(new Event('change', { bubbles: true })); + } + }, cfg.geometry); - // Click generate. - await page.click('#generateBtn'); + // Select the WebGL renderer via its radio button. + await page.evaluate(() => { + const el = document.querySelector('input[name="renderer"][value="webgl"]'); + if (el) { + el.checked = true; + el.dispatchEvent(new Event('change', { bubbles: true })); + } + }); + + // Set the point-count slider and fire both 'input' and 'change' so the app + // debounce timer is triggered and the label is updated. + await page.evaluate((idx: number) => { + const el = document.getElementById('numPoints') as HTMLInputElement | null; + if (el) { + el.value = String(idx); + el.dispatchEvent(new Event('input', { bubbles: true })); + el.dispatchEvent(new Event('change', { bubbles: true })); + } + }, sliderIndex); - // Wait for statPoints to update to the selected N. - const expected = cfg.points.toLocaleString(); + // Wait for statPoints to reflect the newly generated dataset. + const expected = actualPoints.toLocaleString(); await page.waitForFunction( (exp: string) => { const el = document.getElementById('statPoints'); - return !!el && (el.textContent || '').includes(exp); + return !!el && (el.textContent ?? '').includes(exp); }, { timeout: 120000 }, - expected + expected, ); - // Give the app a beat to finish uploading buffers. + // Give the app a beat to finish uploading GPU buffers. await sleep(250); }