RouteFM-Demo / app.js
AIGNLAI's picture
Upload folder using huggingface_hub
b11b0d7 verified
Raw History Blame Contribute Delete
4.57 kB
const state = { data: null, environment: null, target: null, budget: "4", reveal: false };
const $ = (id) => document.getElementById(id);
const letter = (index) => `Candidate ${String.fromCharCode(65 + index)}`;
function fillSelect(select, values) {
select.replaceChildren(...values.map((value) => {
const option = document.createElement("option");
option.value = value;
option.textContent = value;
return option;
}));
}
function candidateName(index) {
return state.reveal ? state.data.environments[state.environment].labels[index] : letter(index);
}
function renderBudgets() {
$("budgets").replaceChildren(...["1", "2", "4", "8"].map((value) => {
const button = document.createElement("button");
button.type = "button";
button.textContent = `K=${value}`;
button.className = value === state.budget ? "active" : "";
button.addEventListener("click", () => { state.budget = value; render(); });
return button;
}));
}
function renderCandidates() {
const result = state.data.environments[state.environment].results[state.budget][state.target];
const selectedIndex = result.scores.indexOf(Math.max(...result.scores));
$("choice").textContent = candidateName(selectedIndex);
$("context-summary").textContent = `K=${state.budget} observations per candidate`;
$("candidate-grid").replaceChildren(...result.scores.map((score, index) => {
const card = document.createElement("article");
card.className = `candidate${index === selectedIndex ? " selected" : ""}`;
const name = document.createElement("div");
name.className = "candidate-top";
const strong = document.createElement("strong");
strong.textContent = candidateName(index);
name.append(strong);
if (index === selectedIndex) {
const badge = document.createElement("span"); badge.textContent = "selected"; name.append(badge);
}
card.append(name, measure("Predicted quality", score, false), measure("Predicted relative cost", result.costs[index], true));
return card;
}));
}
function measure(label, value, cost) {
const wrap = document.createElement("div"); wrap.className = `measure${cost ? " cost" : ""}`;
const row = document.createElement("label"); row.textContent = label;
const number = document.createElement("b"); number.textContent = value.toFixed(3); row.append(number);
const bar = document.createElement("div"); bar.className = "bar";
const fill = document.createElement("i"); fill.style.width = `${Math.min(100, Math.max(0, value * 100))}%`; bar.append(fill);
wrap.append(row, bar); return wrap;
}
function renderContext() {
const env = state.data.environments[state.environment];
const header = document.createElement("tr");
["Context query", ...env.labels.flatMap((_, index) => [`${String.fromCharCode(65 + index)} · score`, `${String.fromCharCode(65 + index)} · cost`])].forEach((value) => {
const th = document.createElement("th"); th.textContent = value; header.append(th);
});
$("context-head").replaceChildren(header);
$("context-body").replaceChildren(...env.observations.slice(0, Number(state.budget)).map((observation) => {
const tr = document.createElement("tr");
[observation.query, ...observation.scores.flatMap((score, index) => [score.toFixed(2), observation.costs[index].toFixed(2)])].forEach((value) => {
const td = document.createElement("td"); td.textContent = value; tr.append(td);
});
return tr;
}));
}
function render() { renderBudgets(); renderCandidates(); renderContext(); }
fetch("data.json").then((response) => {
if (!response.ok) throw new Error(`Could not load demo data (${response.status}).`);
return response.json();
}).then((data) => {
state.data = data;
const environments = Object.keys(data.environments);
state.environment = environments[0];
fillSelect($("environment"), environments);
fillSelect($("target"), data.environments[state.environment].targets);
state.target = data.environments[state.environment].targets[0];
$("environment").addEventListener("change", (event) => {
state.environment = event.target.value;
const targets = data.environments[state.environment].targets;
fillSelect($("target"), targets); state.target = targets[0]; render();
});
$("target").addEventListener("change", (event) => { state.target = event.target.value; renderCandidates(); });
$("reveal").addEventListener("change", (event) => { state.reveal = event.target.checked; renderCandidates(); });
render();
}).catch((error) => {
$("candidate-grid").textContent = error.message;
});