publish current study stats page
Browse files- static/stats.html +169 -0
static/stats.html
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en"><head><meta charset="utf-8">
|
| 3 |
+
<title>User study stats · FrameWorker</title>
|
| 4 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 5 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
|
| 6 |
+
<style>
|
| 7 |
+
:root { --bg:#0f1115; --panel:#161922; --panel-2:#1c2030; --border:#2a2f42;
|
| 8 |
+
--fg:#e6e8ef; --muted:#8b91a8; --accent:#6aa9ff; --good:#28c76f;
|
| 9 |
+
--warn:#ff9f43; --bad:#ea5455; }
|
| 10 |
+
body { margin: 0; background: var(--bg); color: var(--fg);
|
| 11 |
+
font-family: -apple-system, "Inter", "PingFang SC", sans-serif; }
|
| 12 |
+
header { padding: 14px 24px; border-bottom: 1px solid var(--border);
|
| 13 |
+
background: var(--panel); display: flex; gap: 14px; align-items: baseline;
|
| 14 |
+
flex-wrap: wrap; }
|
| 15 |
+
header h1 { font-size: 18px; margin: 0; }
|
| 16 |
+
header .meta { color: var(--muted); font-size: 12px; }
|
| 17 |
+
main { padding: 18px 24px; max-width: 1100px; margin: 0 auto; }
|
| 18 |
+
section { background: var(--panel); border: 1px solid var(--border);
|
| 19 |
+
border-radius: 8px; padding: 16px 18px; margin-bottom: 16px; }
|
| 20 |
+
h2 { font-size: 15px; margin: 0 0 12px; color: var(--accent); }
|
| 21 |
+
table { border-collapse: collapse; width: 100%; font-size: 13px; }
|
| 22 |
+
th, td { padding: 6px 10px; border-bottom: 1px solid var(--border); text-align: left; }
|
| 23 |
+
th { color: var(--muted); font-weight: 600; font-size: 11px;
|
| 24 |
+
text-transform: uppercase; letter-spacing: 0.5px; }
|
| 25 |
+
.q-block { background: var(--panel-2); border: 1px solid var(--border);
|
| 26 |
+
border-radius: 6px; padding: 10px 12px; margin: 10px 0; }
|
| 27 |
+
.q-block .q-title { font-weight: 600; font-size: 13px; margin-bottom: 4px; }
|
| 28 |
+
.q-block .q-dim { color: var(--muted); font-size: 11px; }
|
| 29 |
+
canvas { background: transparent; max-height: 240px; }
|
| 30 |
+
.legend-dot { display: inline-block; width: 9px; height: 9px;
|
| 31 |
+
border-radius: 50%; margin-right: 4px; vertical-align: middle; }
|
| 32 |
+
.empty { color: var(--muted); font-size: 12px; padding: 20px;
|
| 33 |
+
text-align: center; background: var(--panel-2); border-radius: 6px; }
|
| 34 |
+
</style></head><body>
|
| 35 |
+
|
| 36 |
+
<header>
|
| 37 |
+
<h1>User study stats</h1>
|
| 38 |
+
<span class="meta">generated <code id="ts"></code> · raters <b id="nrater"></b>
|
| 39 |
+
· submissions <b id="nfile"></b> · 1–5 Likert</span>
|
| 40 |
+
<span style="margin-left:auto"><a href="./" style="color:var(--accent)">← back to study</a></span>
|
| 41 |
+
</header>
|
| 42 |
+
|
| 43 |
+
<main>
|
| 44 |
+
<section>
|
| 45 |
+
<h2>Per dimension</h2>
|
| 46 |
+
<canvas id="dimChart"></canvas>
|
| 47 |
+
<table style="margin-top:12px"><thead><tr id="dimHead"></tr></thead>
|
| 48 |
+
<tbody id="dimBody"></tbody></table>
|
| 49 |
+
</section>
|
| 50 |
+
|
| 51 |
+
<section>
|
| 52 |
+
<h2>Per sub-question</h2>
|
| 53 |
+
<table><thead><tr id="qHead"></tr></thead><tbody id="qBody"></tbody></table>
|
| 54 |
+
</section>
|
| 55 |
+
|
| 56 |
+
<section>
|
| 57 |
+
<h2>Per sub-question — model comparison</h2>
|
| 58 |
+
<div id="qCharts"></div>
|
| 59 |
+
</section>
|
| 60 |
+
</main>
|
| 61 |
+
|
| 62 |
+
<script id="data" type="application/json">{"n_raters": 3, "n_payloads": 4, "models": ["ours", "baseline", "huobao"], "per_question": [{"dim_label": "Instruction following", "q_label": "Controllability", "q_key": "controllability", "scores": {"ours": [3, 3, 3, 3, 3, 5, 5, 3, 4, 4, 3, 3, 3, 3, 3, 5, 5, 3, 4, 4], "baseline": [1, 3, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 1, 3, 3, 1, 1, 1, 1, 1], "huobao": [1, 3, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 1, 3, 3, 1, 1, 1, 1, 1]}}, {"dim_label": "Instruction following", "q_label": "Prompt adherence", "q_key": "prompt_adherence", "scores": {"ours": [3, 1, 3, 3, 2, 4, 4, 5, 3, 5, 3, 1, 3, 3, 2, 4, 4, 5, 3, 5], "baseline": [1, 2, 3, 4, 3, 2, 4, 3, 3, 4, 1, 2, 3, 4, 3, 2, 4, 3, 3, 4], "huobao": [3, 3, 2, 4, 4, 2, 2, 4, 5, 4, 3, 3, 2, 4, 4, 2, 2, 4, 5, 4]}}, {"dim_label": "Instruction following", "q_label": "No irrelevant frames", "q_key": "no_irrelevant_frames", "scores": {"ours": [2, 2, 2, 3, 2, 3, 4, 2, 5, 4, 2, 2, 2, 3, 2, 3, 4, 2, 5, 4], "baseline": [2, 2, 1, 4, 4, 3, 4, 1, 2, 4, 2, 2, 1, 4, 4, 3, 4, 1, 2, 4], "huobao": [2, 2, 3, 2, 3, 1, 3, 2, 4, 4, 2, 2, 3, 2, 3, 1, 3, 2, 4, 4]}}, {"dim_label": "Temporal consistency", "q_label": "Person stability", "q_key": "person_stability", "scores": {"ours": [2, 2, 3, 2, 5, 3, 3, 4, 5, 5, 2, 2, 3, 2, 5, 3, 3, 4, 5, 5], "baseline": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], "huobao": [3, 1, 2, 1, 2, 1, 1, 2, 3, 3, 3, 1, 2, 1, 2, 1, 1, 2, 3, 3]}}, {"dim_label": "Temporal consistency", "q_label": "Object stability", "q_key": "object_stability", "scores": {"ours": [4, 2, 2, 5, 3, 4, 3, 4, 5, 5, 4, 2, 2, 5, 3, 4, 3, 4, 5, 5], "baseline": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], "huobao": [4, 1, 3, 1, 3, 1, 1, 1, 4, 2, 4, 1, 3, 1, 3, 1, 1, 1, 4, 2]}}, {"dim_label": "Temporal consistency", "q_label": "Environment stability", "q_key": "environment_stability", "scores": {"ours": [2, 3, 5, 3, 4, 4, 4, 5, 5, 5, 2, 3, 5, 3, 4, 4, 4, 5, 5, 5], "baseline": [1, 1, 1, 2, 3, 1, 1, 1, 3, 2, 1, 1, 1, 2, 3, 1, 1, 1, 3, 2], "huobao": [2, 1, 4, 1, 4, 1, 2, 1, 3, 3, 2, 1, 4, 1, 4, 1, 2, 1, 3, 3]}}, {"dim_label": "Realism", "q_label": "Realism", "q_key": "realism", "scores": {"ours": [2, 2, 3, 3, 2, 2, 3, 4, 2, 3, 2, 2, 3, 3, 2, 2, 3, 4, 2, 3], "baseline": [1, 2, 4, 2, 1, 1, 2, 1, 4, 4, 1, 2, 4, 2, 1, 1, 2, 1, 4, 4], "huobao": [2, 1, 2, 2, 2, 1, 1, 4, 4, 2, 2, 1, 2, 2, 2, 1, 1, 4, 4, 2]}}, {"dim_label": "Realism", "q_label": "Motion logic", "q_key": "motion_logic", "scores": {"ours": [2, 3, 2, 2, 3, 4, 2, 4, 2, 2, 2, 3, 2, 2, 3, 4, 2, 4, 2, 2], "baseline": [3, 3, 3, 2, 1, 2, 3, 1, 1, 2, 3, 3, 3, 2, 1, 2, 3, 1, 1, 2], "huobao": [3, 1, 1, 2, 3, 3, 1, 3, 1, 3, 3, 1, 1, 2, 3, 3, 1, 3, 1, 3]}}, {"dim_label": "Realism", "q_label": "Camera", "q_key": "camera", "scores": {"ours": [4, 3, 3, 3, 3, 4, 2, 5, 3, 4, 4, 3, 3, 3, 3, 4, 2, 5, 3, 4], "baseline": [2, 1, 2, 2, 3, 2, 1, 2, 2, 2, 2, 1, 2, 2, 3, 2, 1, 2, 2, 2], "huobao": [3, 1, 2, 2, 3, 3, 1, 3, 2, 2, 3, 1, 2, 2, 3, 3, 1, 3, 2, 2]}}], "per_dim": [{"dim_label": "Instruction following", "scores": {"ours": [3, 3, 3, 3, 3, 5, 5, 3, 4, 4, 3, 3, 3, 3, 3, 5, 5, 3, 4, 4, 3, 1, 3, 3, 2, 4, 4, 5, 3, 5, 3, 1, 3, 3, 2, 4, 4, 5, 3, 5, 2, 2, 2, 3, 2, 3, 4, 2, 5, 4, 2, 2, 2, 3, 2, 3, 4, 2, 5, 4], "baseline": [1, 3, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 1, 3, 3, 1, 1, 1, 1, 1, 1, 2, 3, 4, 3, 2, 4, 3, 3, 4, 1, 2, 3, 4, 3, 2, 4, 3, 3, 4, 2, 2, 1, 4, 4, 3, 4, 1, 2, 4, 2, 2, 1, 4, 4, 3, 4, 1, 2, 4], "huobao": [1, 3, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 1, 3, 3, 1, 1, 1, 1, 1, 3, 3, 2, 4, 4, 2, 2, 4, 5, 4, 3, 3, 2, 4, 4, 2, 2, 4, 5, 4, 2, 2, 3, 2, 3, 1, 3, 2, 4, 4, 2, 2, 3, 2, 3, 1, 3, 2, 4, 4]}}, {"dim_label": "Temporal consistency", "scores": {"ours": [2, 2, 3, 2, 5, 3, 3, 4, 5, 5, 2, 2, 3, 2, 5, 3, 3, 4, 5, 5, 4, 2, 2, 5, 3, 4, 3, 4, 5, 5, 4, 2, 2, 5, 3, 4, 3, 4, 5, 5, 2, 3, 5, 3, 4, 4, 4, 5, 5, 5, 2, 3, 5, 3, 4, 4, 4, 5, 5, 5], "baseline": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 3, 2, 1, 1, 1, 2, 3, 1, 1, 1, 3, 2], "huobao": [3, 1, 2, 1, 2, 1, 1, 2, 3, 3, 3, 1, 2, 1, 2, 1, 1, 2, 3, 3, 4, 1, 3, 1, 3, 1, 1, 1, 4, 2, 4, 1, 3, 1, 3, 1, 1, 1, 4, 2, 2, 1, 4, 1, 4, 1, 2, 1, 3, 3, 2, 1, 4, 1, 4, 1, 2, 1, 3, 3]}}, {"dim_label": "Realism", "scores": {"ours": [2, 2, 3, 3, 2, 2, 3, 4, 2, 3, 2, 2, 3, 3, 2, 2, 3, 4, 2, 3, 2, 3, 2, 2, 3, 4, 2, 4, 2, 2, 2, 3, 2, 2, 3, 4, 2, 4, 2, 2, 4, 3, 3, 3, 3, 4, 2, 5, 3, 4, 4, 3, 3, 3, 3, 4, 2, 5, 3, 4], "baseline": [1, 2, 4, 2, 1, 1, 2, 1, 4, 4, 1, 2, 4, 2, 1, 1, 2, 1, 4, 4, 3, 3, 3, 2, 1, 2, 3, 1, 1, 2, 3, 3, 3, 2, 1, 2, 3, 1, 1, 2, 2, 1, 2, 2, 3, 2, 1, 2, 2, 2, 2, 1, 2, 2, 3, 2, 1, 2, 2, 2], "huobao": [2, 1, 2, 2, 2, 1, 1, 4, 4, 2, 2, 1, 2, 2, 2, 1, 1, 4, 4, 2, 3, 1, 1, 2, 3, 3, 1, 3, 1, 3, 3, 1, 1, 2, 3, 3, 1, 3, 1, 3, 3, 1, 2, 2, 3, 3, 1, 3, 2, 2, 3, 1, 2, 2, 3, 3, 1, 3, 2, 2]}}], "generated_at_utc": "2026-05-11T19:44:11Z"}</script>
|
| 63 |
+
<script>
|
| 64 |
+
const DATA = JSON.parse(document.getElementById("data").textContent);
|
| 65 |
+
const COLORS = ["#6aa9ff","#ff9f43","#28c76f","#ea5455","#b46aff"];
|
| 66 |
+
const MODEL_COLOR = Object.fromEntries(DATA.models.map((m,i) => [m, COLORS[i % COLORS.length]]));
|
| 67 |
+
|
| 68 |
+
document.getElementById("ts").textContent = DATA.generated_at_utc;
|
| 69 |
+
document.getElementById("nrater").textContent = DATA.n_raters;
|
| 70 |
+
document.getElementById("nfile").textContent = DATA.n_payloads;
|
| 71 |
+
|
| 72 |
+
function mean(arr) { return arr.length ? arr.reduce((a,b)=>a+b,0)/arr.length : null; }
|
| 73 |
+
function std(arr) {
|
| 74 |
+
if (arr.length < 2) return 0;
|
| 75 |
+
const m = mean(arr); const v = arr.reduce((a,b)=>a+(b-m)*(b-m),0)/(arr.length-1);
|
| 76 |
+
return Math.sqrt(v);
|
| 77 |
+
}
|
| 78 |
+
function fmt(arr) {
|
| 79 |
+
if (!arr.length) return "—";
|
| 80 |
+
const m = mean(arr); const s = std(arr);
|
| 81 |
+
return arr.length > 1 ? `${m.toFixed(2)} ± ${s.toFixed(2)} (n=${arr.length})`
|
| 82 |
+
: `${m.toFixed(2)} (n=${arr.length})`;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
/* Dimension table + bar chart */
|
| 86 |
+
{
|
| 87 |
+
const head = document.getElementById("dimHead");
|
| 88 |
+
head.innerHTML = "<th>Dimension</th>" + DATA.models.map(m =>
|
| 89 |
+
`<th><span class="legend-dot" style="background:${MODEL_COLOR[m]}"></span>${m}</th>`).join("");
|
| 90 |
+
const body = document.getElementById("dimBody");
|
| 91 |
+
for (const d of DATA.per_dim) {
|
| 92 |
+
const tr = document.createElement("tr");
|
| 93 |
+
tr.innerHTML = `<td>${d.dim_label}</td>` +
|
| 94 |
+
DATA.models.map(m => `<td>${fmt(d.scores[m] || [])}</td>`).join("");
|
| 95 |
+
body.appendChild(tr);
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
const labels = DATA.per_dim.map(d => d.dim_label);
|
| 99 |
+
const datasets = DATA.models.map(m => ({
|
| 100 |
+
label: m,
|
| 101 |
+
data: DATA.per_dim.map(d => mean(d.scores[m] || [])),
|
| 102 |
+
backgroundColor: MODEL_COLOR[m] + "cc",
|
| 103 |
+
borderColor: MODEL_COLOR[m], borderWidth: 1,
|
| 104 |
+
}));
|
| 105 |
+
new Chart(document.getElementById("dimChart"), {
|
| 106 |
+
type: "bar",
|
| 107 |
+
data: { labels, datasets },
|
| 108 |
+
options: {
|
| 109 |
+
responsive: true, scales: {
|
| 110 |
+
y: { min: 0, max: 5, ticks: { color: "#8b91a8" }, grid: { color: "#2a2f42" } },
|
| 111 |
+
x: { ticks: { color: "#e6e8ef" }, grid: { display: false } },
|
| 112 |
+
},
|
| 113 |
+
plugins: { legend: { labels: { color: "#e6e8ef" } } },
|
| 114 |
+
},
|
| 115 |
+
});
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
/* Per-question table */
|
| 119 |
+
{
|
| 120 |
+
const head = document.getElementById("qHead");
|
| 121 |
+
head.innerHTML = "<th>Dim</th><th>Sub-question</th>" + DATA.models.map(m =>
|
| 122 |
+
`<th><span class="legend-dot" style="background:${MODEL_COLOR[m]}"></span>${m}</th>`).join("");
|
| 123 |
+
const body = document.getElementById("qBody");
|
| 124 |
+
for (const q of DATA.per_question) {
|
| 125 |
+
const tr = document.createElement("tr");
|
| 126 |
+
tr.innerHTML = `<td>${q.dim_label}</td><td>${q.q_label}</td>` +
|
| 127 |
+
DATA.models.map(m => `<td>${fmt(q.scores[m] || [])}</td>`).join("");
|
| 128 |
+
body.appendChild(tr);
|
| 129 |
+
}
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
/* One mini bar chart per sub-question */
|
| 133 |
+
{
|
| 134 |
+
const wrap = document.getElementById("qCharts");
|
| 135 |
+
for (const q of DATA.per_question) {
|
| 136 |
+
const total = DATA.models.reduce((n, m) => n + (q.scores[m] || []).length, 0);
|
| 137 |
+
const block = document.createElement("div");
|
| 138 |
+
block.className = "q-block";
|
| 139 |
+
block.innerHTML = `<div class="q-title">${q.q_label}</div>
|
| 140 |
+
<div class="q-dim">${q.dim_label}</div>`;
|
| 141 |
+
if (!total) {
|
| 142 |
+
const e = document.createElement("div");
|
| 143 |
+
e.className = "empty"; e.textContent = "(no ratings yet)";
|
| 144 |
+
block.appendChild(e); wrap.appendChild(block); continue;
|
| 145 |
+
}
|
| 146 |
+
const c = document.createElement("canvas");
|
| 147 |
+
block.appendChild(c); wrap.appendChild(block);
|
| 148 |
+
const datasets = DATA.models.map(m => ({
|
| 149 |
+
label: m,
|
| 150 |
+
data: [mean(q.scores[m] || [])],
|
| 151 |
+
backgroundColor: MODEL_COLOR[m] + "cc",
|
| 152 |
+
borderColor: MODEL_COLOR[m], borderWidth: 1,
|
| 153 |
+
}));
|
| 154 |
+
new Chart(c, {
|
| 155 |
+
type: "bar",
|
| 156 |
+
data: { labels: [q.q_label], datasets },
|
| 157 |
+
options: {
|
| 158 |
+
indexAxis: "y", responsive: true,
|
| 159 |
+
scales: {
|
| 160 |
+
x: { min: 0, max: 5, ticks: { color: "#8b91a8" }, grid: { color: "#2a2f42" } },
|
| 161 |
+
y: { ticks: { display: false }, grid: { display: false } },
|
| 162 |
+
},
|
| 163 |
+
plugins: { legend: { labels: { color: "#e6e8ef" } } },
|
| 164 |
+
},
|
| 165 |
+
});
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
</script>
|
| 169 |
+
</body></html>
|