Spaces:
Running
Running
Delete assets/js/homepage.js
Browse files- assets/js/homepage.js +0 -159
assets/js/homepage.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
| 1 |
-
const NEUTRAL_LABELS = new Set(["Time", "Success", "Failure"]);
|
| 2 |
-
|
| 3 |
-
const FAILURE_DETAILS = {
|
| 4 |
-
"Safety Conflict":
|
| 5 |
-
"Unintended physical contact between the human and robot outside the designed workflow.",
|
| 6 |
-
"Safety Avoidance":
|
| 7 |
-
"Human visibly alters their trajectory to avoid potential contact with the robot.",
|
| 8 |
-
"Passive Wait":
|
| 9 |
-
"Human remains idle while useful work is available because they defer to the robot.",
|
| 10 |
-
"Redundant Retrieval":
|
| 11 |
-
"Both agents retrieve the same item, wasting effort through duplication.",
|
| 12 |
-
"Task Model Uncertainty":
|
| 13 |
-
"Human hesitates due to uncertainty about the next task step or target.",
|
| 14 |
-
"Capability Miscalibration":
|
| 15 |
-
"Human waits for a robot capability that does not exist or will not execute.",
|
| 16 |
-
"Missed Grab":
|
| 17 |
-
"Human or robot attempts to grasp an item but fails to secure it.",
|
| 18 |
-
Slippage:
|
| 19 |
-
"Bottle unintentionally slips from grasp during motion, requiring recovery."
|
| 20 |
-
};
|
| 21 |
-
|
| 22 |
-
const kindColors = {
|
| 23 |
-
Safety: "#f97316",
|
| 24 |
-
Timing: "#22c55e",
|
| 25 |
-
Effort: "#eab308",
|
| 26 |
-
Execution: "#a855f7"
|
| 27 |
-
};
|
| 28 |
-
|
| 29 |
-
const searchInput = document.getElementById("searchFail");
|
| 30 |
-
const grid = document.getElementById("failureGrid");
|
| 31 |
-
const emptyState = document.getElementById("emptyState");
|
| 32 |
-
const totalCount = document.getElementById("totalCount");
|
| 33 |
-
const videoCount = document.getElementById("videoCount");
|
| 34 |
-
|
| 35 |
-
async function loadCSV() {
|
| 36 |
-
const candidates = [
|
| 37 |
-
'combined_rater_with_embed.csv',
|
| 38 |
-
'./combined_rater_with_embed.csv',
|
| 39 |
-
'data/combined_rater_with_embed.csv',
|
| 40 |
-
'./data/combined_rater_with_embed.csv'
|
| 41 |
-
];
|
| 42 |
-
|
| 43 |
-
for (const p of candidates) {
|
| 44 |
-
try {
|
| 45 |
-
const url = new URL(p, window.location.href).href + '?_=' + Date.now();
|
| 46 |
-
const resp = await fetch(url);
|
| 47 |
-
if (!resp.ok) continue;
|
| 48 |
-
const text = await resp.text();
|
| 49 |
-
return text
|
| 50 |
-
.trim()
|
| 51 |
-
.split("\n")
|
| 52 |
-
.map(line => line.split(","));
|
| 53 |
-
} catch (e) {
|
| 54 |
-
// try next candidate
|
| 55 |
-
}
|
| 56 |
-
}
|
| 57 |
-
throw new Error('could not fetch combined_rater_with_embed.csv from known locations');
|
| 58 |
-
}
|
| 59 |
-
|
| 60 |
-
function formatLabel(label) {
|
| 61 |
-
return label
|
| 62 |
-
.split("_")
|
| 63 |
-
.map(piece => piece.charAt(0).toUpperCase() + piece.slice(1))
|
| 64 |
-
.join(" ");
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
function deriveKind(label) {
|
| 68 |
-
if (/safety/i.test(label)) return "Safety";
|
| 69 |
-
if (/tim|wait|uncertainty|capability/i.test(label)) return "Timing";
|
| 70 |
-
if (/effort|redundant/i.test(label)) return "Effort";
|
| 71 |
-
return "Execution";
|
| 72 |
-
}
|
| 73 |
-
|
| 74 |
-
function renderFailures(rows) {
|
| 75 |
-
const header = rows[0];
|
| 76 |
-
// CSV format: filename,video_id,embed_url,label,rater,start,end
|
| 77 |
-
const failures = new Map();
|
| 78 |
-
|
| 79 |
-
for (let i = 1; i < rows.length; i++) {
|
| 80 |
-
const [filename, video_id, embed_url, rawLabel, rater, start, end] = rows[i];
|
| 81 |
-
if (!rawLabel || NEUTRAL_LABELS.has(rawLabel.trim())) continue;
|
| 82 |
-
const label = rawLabel.trim();
|
| 83 |
-
|
| 84 |
-
if (!failures.has(label)) {
|
| 85 |
-
failures.set(label, {
|
| 86 |
-
label,
|
| 87 |
-
videos: new Set(),
|
| 88 |
-
occurrences: 0
|
| 89 |
-
});
|
| 90 |
-
}
|
| 91 |
-
|
| 92 |
-
const entry = failures.get(label);
|
| 93 |
-
entry.videos.add(filename);
|
| 94 |
-
// Count occurrences where start and end are provided
|
| 95 |
-
if (start && end && start !== "NA" && end !== "NA") {
|
| 96 |
-
entry.occurrences += 1;
|
| 97 |
-
}
|
| 98 |
-
}
|
| 99 |
-
|
| 100 |
-
const failureList = Array.from(failures.values()).sort((a, b) =>
|
| 101 |
-
a.label.localeCompare(b.label)
|
| 102 |
-
);
|
| 103 |
-
|
| 104 |
-
totalCount.textContent = `${failureList.length} failures`;
|
| 105 |
-
const totalVideos = failureList.reduce(
|
| 106 |
-
(sum, item) => sum + item.videos.size,
|
| 107 |
-
0
|
| 108 |
-
);
|
| 109 |
-
videoCount.textContent = `${totalVideos} videos impacted`;
|
| 110 |
-
|
| 111 |
-
function applyFilter(term) {
|
| 112 |
-
const lower = term.trim().toLowerCase();
|
| 113 |
-
let any = false;
|
| 114 |
-
grid.innerHTML = "";
|
| 115 |
-
|
| 116 |
-
failureList.forEach(item => {
|
| 117 |
-
if (lower && !item.label.toLowerCase().includes(lower)) {
|
| 118 |
-
return;
|
| 119 |
-
}
|
| 120 |
-
|
| 121 |
-
any = true;
|
| 122 |
-
const pretty = formatLabel(item.label);
|
| 123 |
-
const kind = deriveKind(item.label);
|
| 124 |
-
const definition =
|
| 125 |
-
FAILURE_DETAILS[pretty] ||
|
| 126 |
-
FAILURE_DETAILS[item.label] ||
|
| 127 |
-
"No description recorded yet.";
|
| 128 |
-
|
| 129 |
-
const card = document.createElement("article");
|
| 130 |
-
card.className = "failure-card";
|
| 131 |
-
card.innerHTML = `
|
| 132 |
-
<div class="meta-row">
|
| 133 |
-
<span style="color:${kindColors[kind] || "#38bdf8"}">${kind}</span>
|
| 134 |
-
<span>${item.videos.size} videos</span>
|
| 135 |
-
</div>
|
| 136 |
-
<h3>${pretty}</h3>
|
| 137 |
-
<p>${definition}</p>
|
| 138 |
-
<div class="tooltip">
|
| 139 |
-
${definition}
|
| 140 |
-
</div>
|
| 141 |
-
`;
|
| 142 |
-
card.addEventListener("click", () => {
|
| 143 |
-
window.location.href = "codebook.html#" + encodeURIComponent(item.label);
|
| 144 |
-
});
|
| 145 |
-
grid.appendChild(card);
|
| 146 |
-
});
|
| 147 |
-
|
| 148 |
-
emptyState.hidden = any;
|
| 149 |
-
}
|
| 150 |
-
|
| 151 |
-
applyFilter("");
|
| 152 |
-
searchInput.addEventListener("input", e => applyFilter(e.target.value));
|
| 153 |
-
}
|
| 154 |
-
|
| 155 |
-
loadCSV().then(renderFailures).catch(err => {
|
| 156 |
-
grid.innerHTML = `<div class="empty-state">Failed to load CSV: ${err.message}</div>`;
|
| 157 |
-
emptyState.hidden = true;
|
| 158 |
-
});
|
| 159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|