Ladefehler
${error.message}
const formatHours = (value) => `${Number(value).toFixed(1)} h`;
const create = (tag, className, text) => {
const node = document.createElement(tag);
if (className) node.className = className;
if (text !== undefined) node.textContent = text;
return node;
};
const load = async () => {
const response = await fetch("./data/analysis.json");
if (!response.ok) throw new Error("analysis.json konnte nicht geladen werden");
return response.json();
};
const renderHero = (data) => {
document.querySelector("#headline").textContent = data.executive_summary.headline;
const panel = document.querySelector("#heroPanel");
const stats = [
["Best Estimate", formatHours(data.work_estimate.best_estimate_hours)],
["Aktive Projekte", String(data.work_estimate.active_project_count)],
["Top Empfehlung", data.rankings.top_recommendation.name],
["Analysefenster", `${data.meta.window_start} bis ${data.meta.window_end}`],
];
stats.forEach(([label, value]) => {
const row = create("div", "summary-stat");
row.append(create("span", "", label));
row.append(create("strong", "", value));
panel.append(row);
});
};
const renderFindings = (data) => {
const host = document.querySelector("#findingCards");
data.executive_summary.key_findings.forEach((finding, index) => {
const card = create("article", "card");
card.append(create("div", "label", `Antwort ${index + 1}`));
card.append(create("p", "supporting", finding));
host.append(card);
});
};
const renderWork = (data) => {
const host = document.querySelector("#workCards");
const cards = [
["Best Estimate", formatHours(data.work_estimate.best_estimate_hours), "Zentralwert aus Session-Bloecken, Commit-Spans und Artefakt-Bonus."],
["Untergrenze", formatHours(data.work_estimate.lower_bound_hours), "Konservative Sicht: nur ein Teil der Session-Zeit zaehlt als aktive Build-Zeit."],
["Obergrenze", formatHours(data.work_estimate.upper_bound_hours), "Erweitert um stille Vor-/Nacharbeit, verworfene Versuche und uncommitted Arbeit."],
];
cards.forEach(([label, metric, support]) => {
const card = create("article", "card");
card.append(create("div", "label", label));
card.append(create("p", "metric", metric));
card.append(create("p", "supporting", support));
host.append(card);
});
const methodList = document.querySelector("#methodList");
data.work_estimate.method.forEach((line) => methodList.append(create("li", "", line)));
const uncertaintyList = document.querySelector("#uncertaintyList");
data.work_estimate.uncertainties.forEach((line) => uncertaintyList.append(create("li", "", line)));
};
const renderWorkflow = (data) => {
const workflow = data.workflow_patterns;
const narrative = document.querySelector("#workflowNarrative");
[workflow.startup_pattern, workflow.iteration_pattern, workflow.parallel_vs_serial.evidence].forEach((line) => {
narrative.append(create("p", "", line));
});
const total = workflow.prototyping_vs_refinement.prototype_signals + workflow.prototyping_vs_refinement.refinement_signals;
const protoPct = total ? (workflow.prototyping_vs_refinement.prototype_signals / total) * 100 : 0;
const refinePct = 100 - protoPct;
const chart = document.querySelector("#ratioChart");
[
["Prototyping", protoPct, "proto"],
["Refinement", refinePct, "refine"],
].forEach(([label, pct, klass]) => {
const row = create("div", "mini-row");
row.append(create("div", "", label));
const track = create("div", "track");
const fill = create("span");
fill.className = klass;
fill.style.width = `${pct}%`;
track.append(fill);
row.append(track);
row.append(create("div", "muted", `${pct.toFixed(0)}%`));
chart.append(row);
});
document.querySelector("#ratioNote").textContent = workflow.prototyping_vs_refinement.interpretation;
const cards = [
["Seriell vs. Parallel", workflow.parallel_vs_serial.label],
["Eval-Loops", workflow.evaluation_loops.interpretation],
["Bevorzugte Projektarten", workflow.preferred_project_types.join(" • ")],
["Meta-Systeme", workflow.meta_systems.join(" • ")],
];
const host = document.querySelector("#workflowCards");
cards.forEach(([label, support]) => {
const card = create("article", "card");
card.append(create("div", "label", label));
card.append(create("p", "supporting", support));
host.append(card);
});
};
const renderClusters = (data) => {
const grid = document.querySelector("#clusterGrid");
data.project_clusters.forEach((cluster) => {
const card = create("article", "cluster-card");
card.append(create("div", "label", `${cluster.count} Projekte`));
card.append(create("h3", "", cluster.name));
card.append(create("p", "supporting", cluster.summary));
const pills = create("div", "pill-row");
cluster.projects.forEach((project) => {
pills.append(create("span", "pill", `${project.name} · ${project.commit_count}`));
});
card.append(pills);
grid.append(card);
});
const tableHost = document.querySelector("#projectTable");
const table = create("table");
table.innerHTML = `
Projekt
Cluster
Commits
Sessions
Status
${project.summary}
`; topThree.append(item); }); const rankingTable = document.querySelector("#rankingTable"); const table = create("table"); table.innerHTML = `${error.message}