This is an automated email from the ASF dual-hosted git repository.

Gerrrr pushed a commit to branch multiple-algorithms-single-point
in repository https://gitbox.apache.org/repos/asf/otava-playground.git

commit 828fc44b2c1888b26129d6847d8e523cb7345f72
Author: Alex Sorokoumov <[email protected]>
AuthorDate: Sun Jul 5 10:47:32 2026 -0700

    Prepare per-algorithm Otava UI plumbing
    
    Add canonical algorithm ordering, compact labels, reusable compare fetch 
plumbing, and table/header markup and styles needed by per-algorithm views.
---
 src/otava_test_data/web/static/css/style.css | 50 ++++++++++++++++++++++++++++
 src/otava_test_data/web/static/js/app.js     | 43 ++++++++++++++++++++++++
 src/otava_test_data/web/templates/index.html |  7 ++--
 3 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/src/otava_test_data/web/static/css/style.css 
b/src/otava_test_data/web/static/css/style.css
index 2d1bf63..59830aa 100644
--- a/src/otava_test_data/web/static/css/style.css
+++ b/src/otava_test_data/web/static/css/style.css
@@ -2079,3 +2079,53 @@ body[data-mode="dataset"] .hide-in-dataset {
 .otava-algo:has(.otava-algo-checkbox:not(:checked)) .algo-params {
     opacity: 0.45;
 }
+
+/* ── Per-algorithm Otava visualization ───────────────────────────── */
+
+/* Status text colors used inside detected-table per-algo cells. */
+.pvalue-tp { color: #10b981; font-weight: 600; }
+.pvalue-cm { color: #f59e0b; font-weight: 600; }
+.pvalue-fp { color: #ef4444; font-weight: 600; }
+.pvalue-empty { color: #cbd5e1; }
+
+/* Dots used in the ground-truth "Matched by" column and the stat card. */
+.algo-dot {
+    display: inline-block;
+    width: 9px;
+    height: 9px;
+    border-radius: 50%;
+    vertical-align: middle;
+    margin-right: 4px;
+}
+.algo-dot-split         { background: #1f77b4; }
+.algo-dot-orig          { background: #d62728; }
+.algo-dot-deterministic { background: #2ca02c; }
+
+/* Per-algorithm segments inside the "Otava Detected" stat card. */
+.otava-stat-segments {
+    display: inline-flex;
+    gap: 8px;
+    flex-wrap: wrap;
+    font-size: 0.85rem;
+}
+.otava-stat-segment {
+    display: inline-flex;
+    align-items: center;
+    gap: 4px;
+    line-height: 1;
+}
+.otava-stat-label { color: #64748b; font-size: 0.75rem; }
+
+/* Matched-by column inner layout — one dot+text per algo, dot-separated. */
+.matched-by-list {
+    display: inline-flex;
+    flex-wrap: wrap;
+    gap: 0 8px;
+}
+.matched-by-list .matched-entry::after {
+    content: "·";
+    margin-left: 8px;
+    color: #cbd5e1;
+}
+.matched-by-list .matched-entry:last-child::after { content: ""; }
+.matched-entry-miss { color: #cbd5e1; }
diff --git a/src/otava_test_data/web/static/js/app.js 
b/src/otava_test_data/web/static/js/app.js
index 32b032c..68d1ded 100644
--- a/src/otava_test_data/web/static/js/app.js
+++ b/src/otava_test_data/web/static/js/app.js
@@ -51,6 +51,17 @@ const ALGO_COLORS = {
     deterministic: '#2ca02c',
 };
 
+// Short human-readable labels for compact UI surfaces (stat card, dot lists).
+const ALGO_LABELS = {
+    split:         'split',
+    orig:          'orig',
+    deterministic: 'det',
+};
+
+// Canonical order — drives stat-card layout, accuracy rows, detected columns,
+// and matched-by dots. Iteration order of `ALGO_COLORS` is not guaranteed by 
spec.
+const ALGO_ORDER = ['split', 'orig', 'deterministic'];
+
 // In-flight AbortController for /api/compare so out-of-order responses can't
 // land after a newer one and desync the chart from the controls.
 let datasetInflight = null;
@@ -167,6 +178,38 @@ function getOtavaParamsByAlgo() {
     return out;
 }
 
+/** Call /api/compare with the currently-enabled algorithms and their params.
+ *  Returns Promise<Map<algoName, {indices, count, change_points, error?}>>
+ *  for the algorithms that were actually requested. Order in the returned
+ *  Map follows ALGO_ORDER. */
+async function runOtavaForEnabled(series, { signal } = {}) {
+    const algos = getEnabledOtavaAlgorithms();
+    if (algos.length === 0) return new Map();
+
+    const r = await fetch('/api/compare', {
+        method: 'POST',
+        headers: { 'Content-Type': 'application/json' },
+        body: JSON.stringify({
+            data: series,
+            algorithms: algos,
+            algorithm_params: getOtavaParamsByAlgo(),
+        }),
+        signal,
+    });
+    if (!r.ok) {
+        const err = await r.json().catch(() => ({}));
+        throw new Error(err.error || `HTTP ${r.status}`);
+    }
+    const body = await r.json();
+    const out = new Map();
+    for (const name of ALGO_ORDER) {
+        if (body.results && Object.prototype.hasOwnProperty.call(body.results, 
name)) {
+            out.set(name, body.results[name]);
+        }
+    }
+    return out;
+}
+
 // DOM Elements - Actions
 const generateBtn = document.getElementById('generate-btn');
 const showAllBtn = document.getElementById('show-all-btn');
diff --git a/src/otava_test_data/web/templates/index.html 
b/src/otava_test_data/web/templates/index.html
index 8de8a34..9d35fc1 100644
--- a/src/otava_test_data/web/templates/index.html
+++ b/src/otava_test_data/web/templates/index.html
@@ -470,7 +470,7 @@
                                 <th>Index</th>
                                 <th>Type</th>
                                 <th>Description</th>
-                                <th>Matched?</th>
+                                <th class="matched-col-header">Matched by</th>
                             </tr>
                         </thead>
                         <tbody id="truth-table-body">
@@ -481,12 +481,11 @@
                     <h4>Otava Detected</h4>
                     <table id="detected-table">
                         <thead>
-                            <tr>
+                            <tr id="detected-table-head-row">
                                 <th>Index</th>
                                 <th>Mean Before</th>
                                 <th>Mean After</th>
-                                <th>P-Value</th>
-                                <th>Status</th>
+                                <!-- Per-algorithm columns appended by JS -->
                             </tr>
                         </thead>
                         <tbody id="detected-table-body">

Reply via email to