async function loadJSON(name) {
const res = await fetch(`data/${name}`);
return res.json();
}
const STANCE_LABEL = { pour: 'Pour', contre: 'Contre', divise: 'Divisé' };
function buildCauseNode(cause, causes, partis, facteurById, causeFacteurs, positions) {
const children = causes.filter(c => c.parent_id === cause.id);
const details = document.createElement('details');
const summary = document.createElement('summary');
summary.textContent = `${cause.nom} (${cause.code_cim10})`;
details.appendChild(summary);
if (children.length) {
for (const child of children) {
details.appendChild(buildCauseNode(child, causes, partis, facteurById, causeFacteurs, positions));
}
} else {
details.appendChild(buildFacteurTable(cause.id, partis, facteurById, causeFacteurs, positions));
}
return details;
}
function buildFacteurTable(causeId, partis, facteurById, causeFacteurs, positions) {
const table = document.createElement('table');
const facteurIds = causeFacteurs[causeId] || [];
const thead = document.createElement('tr');
thead.innerHTML = '
Facteur de risque | ' +
partis.map(p => `${p.nom} | `).join('');
table.appendChild(thead);
for (const facteurId of facteurIds) {
const tr = document.createElement('tr');
const facteurCell = document.createElement('td');
facteurCell.textContent = facteurById[facteurId].nom;
tr.appendChild(facteurCell);
for (const parti of partis) {
const td = document.createElement('td');
td.style.background = `${parti.couleur}22`;
const pos = positions.find(p => p.cause_id === causeId && p.facteur_id === facteurId && p.parti_id === parti.id);
if (pos) {
td.classList.add('pos-cell');
td.innerHTML = `${STANCE_LABEL[pos.stance]}`;
td.addEventListener('click', () => showDetail(parti.nom, pos));
} else {
td.textContent = '—';
}
tr.appendChild(td);
}
table.appendChild(tr);
}
return table;
}
function buildFacteursTable(facteurs, causeFacteurs, causes) {
const byId = Object.fromEntries(causes.map(c => [c.id, c]));
const causesByFacteur = {};
for (const [causeId, facteurIds] of Object.entries(causeFacteurs)) {
for (const facteurId of facteurIds) {
(causesByFacteur[facteurId] ??= []).push(causeId);
}
}
const rows = facteurs
.map(f => ({ facteur: f, causeIds: causesByFacteur[f.id] || [] }))
.filter(r => r.causeIds.length > 1)
.sort((a, b) => b.causeIds.length - a.causeIds.length);
const table = document.getElementById('facteurs-table');
const thead = document.createElement('tr');
thead.innerHTML = 'Facteur de risque | Nb causes touchées | Causes concernées | ';
table.appendChild(thead);
for (const row of rows) {
const tr = document.createElement('tr');
const names = row.causeIds.map(id => byId[id].nom).join(', ');
tr.innerHTML = `${row.facteur.nom} | ${row.causeIds.length} | ${names} | `;
table.appendChild(tr);
}
}
async function main() {
const [causes, partis, facteurs, causeFacteurs, positions] = await Promise.all([
loadJSON('causes.json'),
loadJSON('partis.json'),
loadJSON('facteurs.json'),
loadJSON('cause_facteurs.json'),
loadJSON('positions.json'),
]);
const facteurById = Object.fromEntries(facteurs.map(f => [f.id, f]));
const chapitres = causes
.filter(c => c.parent_id === null)
.sort((a, b) => (a.rang ?? 999) - (b.rang ?? 999));
const tree = document.getElementById('causes-tree');
for (const chapitre of chapitres) {
tree.appendChild(buildCauseNode(chapitre, causes, partis, facteurById, causeFacteurs, positions));
}
buildFacteursTable(facteurs, causeFacteurs, causes);
}
function showDetail(partiNom, pos) {
document.getElementById('detail-title').textContent = partiNom;
document.getElementById('detail-text').textContent = pos.position;
const source = document.getElementById('detail-source');
source.href = pos.source_url;
source.textContent = pos.source_url;
document.getElementById('detail').showModal();
}
main();