aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/SanpiTable.astro47
-rw-r--r--src/content/docs/sanpi.mdx1
-rw-r--r--src/styles/custom.css14
3 files changed, 38 insertions, 24 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);
diff --git a/src/content/docs/sanpi.mdx b/src/content/docs/sanpi.mdx
index f3508a3..7891c2d 100644
--- a/src/content/docs/sanpi.mdx
+++ b/src/content/docs/sanpi.mdx
@@ -15,6 +15,7 @@ import SanpiTable from '@/components/SanpiTable.astro';
<SanpiTable />
:::note
+- 議員名は敬称略としています
- 〇=賛成、×=反対、—=表決に加わらない(議長・欠席・退場)
- 議決結果は、可決・認定・採択はグレーの印、否決・不採択は青色の印で示しています(カーソルを合わせると内容が出ます)
- 会派内で賛否が分かれた場合は、同じ賛否の議員は「会派(人数)」にまとめ、異なる議員だけ名前を出して列を分けています。「一人会派と維新の会」は常に議員ごとに示します。安竹洋平の列は色をつけています
diff --git a/src/styles/custom.css b/src/styles/custom.css
index 6552291..740e000 100644
--- a/src/styles/custom.css
+++ b/src/styles/custom.css
@@ -1378,7 +1378,7 @@ td.sanpi-open .sanpi-title {
}
.sanpi-chart-item {
display: grid;
- grid-template-columns: 8.5em 1fr 6.5em;
+ grid-template-columns: 8.5em 1fr 12em;
gap: 0.5rem;
align-items: center;
margin: 0.3rem 0;
@@ -1393,16 +1393,18 @@ td.sanpi-open .sanpi-title {
display: block;
height: 0.9em;
border-radius: 3px;
- background: var(--sl-color-gray-5);
+ /* 背景=反対、塗り=賛成 */
+ background: #e6a6a6;
overflow: hidden;
}
.sanpi-chart-fill {
display: block;
height: 100%;
border-radius: 3px;
+ background: #5b9bd5;
}
.sanpi-chart-val {
- font-size: 0.8em;
+ font-size: 0.75em;
color: var(--sl-color-gray-2);
white-space: nowrap;
text-align: right;
@@ -1410,6 +1412,12 @@ td.sanpi-open .sanpi-title {
.sanpi-chart-val small {
font-size: 0.85em;
}
+:root[data-theme="dark"] .sanpi-chart-bar {
+ background: #6b3b3b;
+}
+:root[data-theme="dark"] .sanpi-chart-fill {
+ background: #4a80b3;
+}
@media (max-width: 480px) {
.sanpi-chart-item {
grid-template-columns: 6em 1fr 5.5em;