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.astro59
1 files changed, 50 insertions, 9 deletions
diff --git a/src/components/SanpiTable.astro b/src/components/SanpiTable.astro
index d85d77f..675d5a0 100644
--- a/src/components/SanpiTable.astro
+++ b/src/components/SanpiTable.astro
@@ -37,6 +37,20 @@
return null;
}
+ // 表に個人名が出ない期間は、所属会派の票をその議員に充当する。
+ // from/until は定例会(令和X年Y月)を基準にする。until を省略すると現在まで。
+ const MEMBER_RULES = [
+ // 中江美和議員は令和3年6月からフォーラム小平。
+ { name: "中江美和", group: "フォ", from: "令和3年6月" },
+ // 石津はるか議員は新議員として政和会に入り、後に一人会派となった。
+ { name: "石津はるか", group: "政和", from: "令和3年6月", until: "令和7年3月" },
+ ];
+
+ function eraKey(text) {
+ const m = (text || "").match(/令和(\d+)年(\d+)月/);
+ return m ? Number(m[1]) * 100 + Number(m[2]) : null;
+ }
+
// 市が提出した議案か(請願・意見書・決議・条例制定・動議などの議員提出議案を除く)。
function isCityBill(cell) {
if (cell.querySelector(".sanpi-shugan")) return false;
@@ -50,23 +64,50 @@
if (!host) return;
const stats = new Map();
- content.querySelectorAll("table").forEach((table) => {
- const headers = [...table.querySelectorAll("thead th")].map((th) => th.textContent.trim());
+ const bump = (name, vote) => {
+ const s = stats.get(name) || { yes: 0, no: 0 };
+ if (vote === "〇") s.yes += 1;
+ else s.no += 1;
+ stats.set(name, s);
+ };
- table.querySelectorAll("tbody tr").forEach((tr) => {
+ // 会派に合流している期間の票を個人に充当する。
+ const applyRules = (groups, cells, sessionKey) => {
+ if (sessionKey == null) return;
+ MEMBER_RULES.forEach((rule) => {
+ const fromKey = eraKey(rule.from);
+ const untilKey = rule.until ? eraKey(rule.until) : Infinity;
+ if (sessionKey < fromKey || sessionKey > untilKey) return;
+ if (groups.includes(rule.name)) return;
+ const gi = groups.indexOf(rule.group);
+ if (gi < 0) return;
+ const vote = voteChar(cells[gi]);
+ if (!vote) return;
+ bump(rule.name, vote);
+ });
+ };
+
+ // 見出し(令和X年Y月定例会)を追いながら、文書順に表を処理する。
+ let sessionKey = null;
+ content.querySelectorAll("h2, table").forEach((el) => {
+ if (el.tagName === "H2") {
+ sessionKey = eraKey(el.textContent);
+ return;
+ }
+ const headers = [...el.querySelectorAll("thead th")].map((th) => th.textContent.trim());
+ const groups = headers.map(groupLabel);
+ el.querySelectorAll("tbody tr").forEach((tr) => {
const cells = [...tr.children];
if (!cells.length || !isCityBill(cells[0])) return;
cells.forEach((cell, i) => {
if (i < 2) return;
- const group = groupLabel(headers[i] || "");
+ const group = groups[i];
if (!group) return;
const vote = voteChar(cell);
if (!vote) return;
- const s = stats.get(group) || { yes: 0, no: 0 };
- if (vote === "〇") s.yes += 1;
- else s.no += 1;
- stats.set(group, s);
+ bump(group, vote);
});
+ applyRules(groups, cells, sessionKey);
});
});
@@ -90,7 +131,7 @@
const caption = document.createElement("p");
caption.className = "sanpi-chart-caption";
caption.textContent =
- "市が提出した議案(請願・意見書・決議・条例制定・動議などの議員提出議案を除く)に対する、会派ごとの議員の賛成・反対の割合です。賛成の割合が高いほど与党寄り、低いほど野党寄りです。会派が分かれた場合は表の各列の票を1件として数えているため、件数が少ない会派は参考程度にご覧ください。";
+ "市が提出した議案(請願・意見書・決議・条例制定・動議などの議員提出議案を除く)に対する、会派ごとの議員の賛成・反対の割合です。賛成の割合が高いほど与党寄り、低いほど野党寄りです。会派が分かれた場合は表の各列の票を1件として数えています。会派に合流している期間(中江美和議員のフォーラム、石津はるか議員の政和会)は、会派の票を個人に充当しています。件数が少ない会派は参考程度にご覧ください。";
const list = document.createElement("ul");
list.className = "sanpi-chart-list";