aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/components/SanpiTable.astro
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/SanpiTable.astro')
-rw-r--r--src/components/SanpiTable.astro47
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);