diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-10 00:02:20 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-10 00:02:20 +0900 |
| commit | f3171ea77bb2200c50e097efea2049426c889705 (patch) | |
| tree | 9d18ab520e89e2929adf3e3fa7341e05fcc660a0 /src/components/SanpiTable.astro | |
| parent | 0851c6ff6cd2bf7ee77fb1d118c34bc381fc3aeb (diff) | |
sanpi: 敬称略の注記を追加し、グラフを市提出議案の賛成・反対率の比較に変更
Diffstat (limited to 'src/components/SanpiTable.astro')
| -rw-r--r-- | src/components/SanpiTable.astro | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/src/components/SanpiTable.astro b/src/components/SanpiTable.astro index 1040bb4..d85d77f 100644 --- a/src/components/SanpiTable.astro +++ b/src/components/SanpiTable.astro @@ -11,8 +11,6 @@ // タップがホバーとして扱われ、ツールチップが残るのを避けるため)。 const CAN_HOVER = window.matchMedia("(hover: hover) and (pointer: fine)").matches; - // 「与党寄り」の基準にする会派(見出しの短名)。 - const REFERENCE = "フォ"; // グラフの先頭に固定する議員(安竹洋平)。 const ME_NAME = "安竹洋平"; // 一人会派のグラフ表示名(議員名を添える)。 @@ -39,7 +37,14 @@ return null; } - // 各会派の賛否が、フォーラム小平とどれだけ一致したか(=与党寄りか)をグラフにする。 + // 市が提出した議案か(請願・意見書・決議・条例制定・動議などの議員提出議案を除く)。 + function isCityBill(cell) { + if (cell.querySelector(".sanpi-shugan")) return false; + const text = cell.textContent || ""; + return !/意見書|決議|動議|制定/.test(text); + } + + // 各会派が市提出議案にどれだけ賛成したか(賛成と反対の割合)をグラフにする。 function buildChart(content) { const host = content.querySelector(".sanpi-chart"); if (!host) return; @@ -47,34 +52,34 @@ const stats = new Map(); content.querySelectorAll("table").forEach((table) => { const headers = [...table.querySelectorAll("thead th")].map((th) => th.textContent.trim()); - const refIdx = headers.findIndex((h) => groupLabel(h) === REFERENCE); - if (refIdx < 0) return; table.querySelectorAll("tbody tr").forEach((tr) => { const cells = [...tr.children]; - const refVote = voteChar(cells[refIdx]); - if (!refVote) return; + if (!cells.length || !isCityBill(cells[0])) return; cells.forEach((cell, i) => { - if (i < 2 || i === refIdx) return; + if (i < 2) return; const group = groupLabel(headers[i] || ""); - if (!group || group === REFERENCE) return; + if (!group) return; const vote = voteChar(cell); if (!vote) return; - const s = stats.get(group) || { match: 0, total: 0 }; - s.total += 1; - if (vote === refVote) s.match += 1; + const s = stats.get(group) || { yes: 0, no: 0 }; + if (vote === "〇") s.yes += 1; + else s.no += 1; stats.set(group, s); }); }); }); const rows = [...stats.entries()] - .map(([group, s]) => ({ group, rate: s.total ? s.match / s.total : 0, total: s.total })) + .map(([group, s]) => { + const total = s.yes + s.no; + return { group, yes: s.yes, no: s.no, total, rate: total ? s.yes / total : 0 }; + }) .filter((row) => row.total > 0) .sort((a, b) => { if (a.group === ME_NAME) return -1; if (b.group === ME_NAME) return 1; - return b.rate - a.rate || a.group.localeCompare(b.group, "ja"); + return b.rate - a.rate || b.total - a.total || a.group.localeCompare(b.group, "ja"); }); if (!rows.length) { @@ -85,13 +90,13 @@ const caption = document.createElement("p"); caption.className = "sanpi-chart-caption"; caption.textContent = - "フォーラム小平と賛否が一致した割合です(〇・×が同じ議案のみを数え、—は除く)。高いほど与党寄り、低いほど野党寄りです。件数が少ない会派は参考程度にご覧ください。"; + "市が提出した議案(請願・意見書・決議・条例制定・動議などの議員提出議案を除く)に対する、会派ごとの議員の賛成・反対の割合です。賛成の割合が高いほど与党寄り、低いほど野党寄りです。会派が分かれた場合は表の各列の票を1件として数えているため、件数が少ない会派は参考程度にご覧ください。"; const list = document.createElement("ul"); list.className = "sanpi-chart-list"; - rows.forEach(({ group, rate, total }) => { - const percent = Math.round(rate * 100); - const hue = Math.round(210 * rate); + rows.forEach(({ group, yes, no, total, rate }) => { + const yesPct = Math.round(rate * 100); + const noPct = 100 - yesPct; const item = document.createElement("li"); item.className = "sanpi-chart-item"; @@ -102,15 +107,15 @@ const bar = document.createElement("span"); bar.className = "sanpi-chart-bar"; + bar.setAttribute("title", `賛成${yes}件/反対${no}件`); const fill = document.createElement("span"); fill.className = "sanpi-chart-fill"; - fill.style.width = `${percent}%`; - fill.style.background = `hsl(${hue} 70% 45%)`; + fill.style.width = `${yesPct}%`; bar.appendChild(fill); const val = document.createElement("span"); val.className = "sanpi-chart-val"; - val.innerHTML = `${percent}%<small>(${total}件)</small>`; + val.innerHTML = `賛成${yesPct}%<small>(${yes})</small>/反対${noPct}%<small>(${no})</small>`; item.append(label, bar, val); list.appendChild(item); |
