模組:LumineRelations
外觀
可在模組:LumineRelations/doc建立此模組的說明文件
--[[
================================================================================
Module:LumineRelations
盧米涅企業共和國 外交關係統計模組
================================================================================
【功能說明】
本模組從「盧米涅企業共和國」頁面的外交表格中自動讀取資料,
計算各項外交統計數值,供 infobox 或正文引用,避免手動維護數字。
【關鍵設計說明】
每張 AutonumTable 的 id(|id=XXX|class=...}})位於表格「結尾」。
因此某張表格的列內容,位於「前一個表格的 id」到「本表格的 id」之間。
本模組使用 countBetween(prevId, thisId) 的方式準確計算每張表格的列數。
頁面中表格的實際順序(必須與頁面一致,否則計算錯誤):
(開頭) → luminebang → luminejing → lumineunilateral → lumineorg
→ luminedc → luminetreaty → luminehistbang → luminehistorg → (結尾)
【可用函式一覽】
--- 正式邦交國 ---
{{#invoke:LumineRelations|bangTotal}} → 邦交國總數
{{#invoke:LumineRelations|bangAmbassador}} → 大使級邦交國數
{{#invoke:LumineRelations|bangMinister}} → 公使級邦交國數
{{#invoke:LumineRelations|bangCharge}} → 代辦級邦交國數
{{#invoke:LumineRelations|bangNA}} → 不適用(特殊外交安排)邦交國數
{{#invoke:LumineRelations|bangFormal}} → 大使+公使+代辦加總(驗算用)
--- 經濟文化代表處 ---
{{#invoke:LumineRelations|jingTotal}} → 設立經濟文化代表處總數
--- 單方承認主權 ---
{{#invoke:LumineRelations|uniTotal}} → 單方承認主權國家總數
--- 加入國際組織 ---
{{#invoke:LumineRelations|orgTotal}} → 加入國際組織總數
--- 深度合作Discord組織 ---
{{#invoke:LumineRelations|dcTotal}} → 深度合作Discord組織總數
--- 同盟及合作協議 ---
{{#invoke:LumineRelations|treatyTotal}} → 締結條約總數
{{#invoke:LumineRelations|treatyMilitary}} → 含軍事性質條約數
{{#invoke:LumineRelations|treatyOther}} → 非軍事性質條約數
--- 歷史邦交國(已斷交)---
{{#invoke:LumineRelations|histTotal}} → 歷史邦交國總數
{{#invoke:LumineRelations|histExtinct}} → 因亡國斷交的數量
{{#invoke:LumineRelations|histMerged}} → 因併入他國斷交的數量
{{#invoke:LumineRelations|histOther}} → 其他原因斷交的數量
--- 歷史參與國際組織(已退出)---
{{#invoke:LumineRelations|histOrgTotal}} → 曾加入但已退出的組織總數
{{#invoke:LumineRelations|histOrgDissolved}} → 因組織解散退出的數量
{{#invoke:LumineRelations|histOrgLeft}} → 主動退出的數量
--- 綜合統計 ---
{{#invoke:LumineRelations|allTotal}} → 邦交國+代表處+組織總計
{{#invoke:LumineRelations|everTotal}} → 曾建交總數(現有+歷史邦交國)
【正文使用範例】
截至目前,盧米涅共與{{#invoke:LumineRelations|bangTotal}}個國家建立正式外交關係,
其中大使級{{#invoke:LumineRelations|bangAmbassador}}個、
公使級{{#invoke:LumineRelations|bangMinister}}個、
代辦級{{#invoke:LumineRelations|bangCharge}}個。
另設有{{#invoke:LumineRelations|jingTotal}}處經濟文化代表處,
並加入{{#invoke:LumineRelations|orgTotal}}個國際組織。
【維護說明】
- 新增或移除表格列後,只需儲存「盧米涅企業共和國」頁面,數字自動更新。
- 若頁面名稱更改,修改 TARGET_PAGE 常數。
- 若表格 id 或順序更改,必須同步修改下方常數。
================================================================================
]]
local p = {}
-- ============================================================
-- 常數設定
-- ============================================================
local TARGET_PAGE = "盧米涅外交"
-- 頁面中各表格的 id(順序必須與頁面實際順序一致)
local ID_BANG = "luminebang" -- 正式邦交國
local ID_JING = "luminejing" -- 經濟文化代表處
local ID_UNI = "lumineunilateral" -- 單方承認主權
local ID_ORG = "lumineorg" -- 加入國際組織
local ID_DC = "luminedc" -- 深度合作Discord組織
local ID_TREATY = "luminetreaty" -- 同盟及合作協議
local ID_HIST = "luminehistbang" -- 歷史邦交國(已斷交)
local ID_HISTORG = "luminehistorg" -- 歷史參與國際組織(已退出)
-- ============================================================
-- 內部工具函式
-- ============================================================
local function getContent()
return mw.title.new(TARGET_PAGE):getContent() or ""
end
-- 計算字串中 AutonumTable/index 的出現次數
local function countIndex(s)
local n = 0
for _ in s:gmatch("AutonumTable/index") do n = n + 1 end
return n
end
-- 核心函式:計算從 prevId 到 thisId 之間的 index 數
-- 因為 id 在表格結尾,所以 prevId~thisId 之間的內容正好是 thisId 對應表格的所有列
-- prevId=nil 表示從頁面開頭,thisId=nil 表示到頁面結尾
local function countBetween(content, prevId, thisId)
local startPos = 1
if prevId then
startPos = content:find("id=" .. prevId)
if not startPos then return 0 end
end
local endPos = #content
if thisId then
endPos = content:find("id=" .. thisId, startPos)
if not endPos then return 0 end
end
return countIndex(content:sub(startPos, endPos))
end
-- 擷取 prevId 到 thisId 之間的字串(用於進一步比對欄位值)
local function getSection(content, prevId, thisId)
local startPos = 1
if prevId then
startPos = content:find("id=" .. prevId)
if not startPos then return "" end
end
local endPos = #content
if thisId then
endPos = content:find("id=" .. thisId, startPos)
if not endPos then return "" end
end
return content:sub(startPos, endPos)
end
-- 計算區段內特定欄位值的出現次數(用 {{!}}{{!}} 包夾精確比對)
local function countField(section, value)
local n = 0
local pattern = "%{%{!%}%}%{%{!%}%}%s*" .. value .. "%s*%{%{!%}%}%{%{!%}%}"
for _ in section:gmatch(pattern) do n = n + 1 end
return n
end
-- ============================================================
-- 正式邦交國(前一表格:無/頁面開頭,本表格 id=luminebang)
-- 欄位:序號 | 國旗及國名 | 建立外交關係時間 | 外交代表機構 | 詳見
-- ============================================================
function p.bangTotal(frame)
return countBetween(getContent(), nil, ID_BANG)
end
function p.bangAmbassador(frame)
return countField(getSection(getContent(), nil, ID_BANG), "大使")
end
function p.bangMinister(frame)
return countField(getSection(getContent(), nil, ID_BANG), "公使")
end
function p.bangCharge(frame)
return countField(getSection(getContent(), nil, ID_BANG), "代辦")
end
function p.bangNA(frame)
return countField(getSection(getContent(), nil, ID_BANG), "不適用")
end
function p.bangFormal(frame)
local s = getSection(getContent(), nil, ID_BANG)
return countField(s, "大使") + countField(s, "公使") + countField(s, "代辦")
end
-- ============================================================
-- 經濟文化代表處(前:luminebang,本:luminejing)
-- 欄位:序號 | 國旗及國名 | 建立關係時間 | 外交代表機構 | 詳見
-- ============================================================
function p.jingTotal(frame)
return countBetween(getContent(), ID_BANG, ID_JING)
end
-- ============================================================
-- 單方承認主權(前:luminejing,本:lumineunilateral)
-- 欄位:序號 | 國旗及國名 | 建立關係時間 | 外交代表機構 | 詳見
-- ============================================================
function p.uniTotal(frame)
return countBetween(getContent(), ID_JING, ID_UNI)
end
-- ============================================================
-- 加入國際組織(前:lumineunilateral,本:lumineorg)
-- 欄位:序號 | 組織徽章及名稱 | 加入時間 | 組織內關係 | 詳見
-- ============================================================
function p.orgTotal(frame)
return countBetween(getContent(), ID_UNI, ID_ORG)
end
-- ============================================================
-- 深度合作Discord組織(前:lumineorg,本:luminedc)
-- 欄位:序號 | 標誌及名稱 | 合作起始時間 | 詳見
-- ============================================================
function p.dcTotal(frame)
return countBetween(getContent(), ID_ORG, ID_DC)
end
-- ============================================================
-- 同盟及合作協議(前:luminedc,本:luminetreaty)
-- 欄位:序號 | 締結條約 | 類型 | 締約成員 | 締約時間
-- ============================================================
function p.treatyTotal(frame)
return countBetween(getContent(), ID_DC, ID_TREATY)
end
-- 含軍事性質的條約數(類型欄包含「軍事」)
function p.treatyMilitary(frame)
local section = getSection(getContent(), ID_DC, ID_TREATY)
local n = 0
for _ in section:gmatch("%{%{!%}%}%{%{!%}%}[^%{]*軍事[^%{]*%{%{!%}%}%{%{!%}%}") do n = n + 1 end
return n
end
-- 非軍事性質條約數
function p.treatyOther(frame)
return (tonumber(p.treatyTotal(frame)) or 0) - (tonumber(p.treatyMilitary(frame)) or 0)
end
-- ============================================================
-- 歷史邦交國(前:luminetreaty,本:luminehistbang)
-- 欄位:序號 | 國旗及國名 | 建立外交關係時間 | 外交代表機構 | 斷交時間 | 斷交原因 | 詳見
-- 斷交原因:「亡國」/ 「併入[[XXX]]」/ 其他
-- ============================================================
function p.histTotal(frame)
return countBetween(getContent(), ID_TREATY, ID_HIST)
end
function p.histExtinct(frame)
return countField(getSection(getContent(), ID_TREATY, ID_HIST), "亡國")
end
function p.histMerged(frame)
local section = getSection(getContent(), ID_TREATY, ID_HIST)
local n = 0
for _ in section:gmatch("%{%{!%}%}%{%{!%}%}%s*併入") do n = n + 1 end
return n
end
function p.histOther(frame)
return (tonumber(p.histTotal(frame)) or 0)
- (tonumber(p.histExtinct(frame)) or 0)
- (tonumber(p.histMerged(frame)) or 0)
end
-- ============================================================
-- 歷史參與國際組織(前:luminehistbang,本:luminehistorg)
-- 欄位:序號 | 組織徽章及名稱 | 加入時間 | 退出時間 | 退出原因 | 組織內關係 | 詳見
-- 退出原因:「組織解散」/ 其他(主動退出)
-- ============================================================
function p.histOrgTotal(frame)
return countBetween(getContent(), ID_HIST, ID_HISTORG)
end
function p.histOrgDissolved(frame)
return countField(getSection(getContent(), ID_HIST, ID_HISTORG), "組織解散")
end
function p.histOrgLeft(frame)
return (tonumber(p.histOrgTotal(frame)) or 0) - (tonumber(p.histOrgDissolved(frame)) or 0)
end
-- ============================================================
-- 綜合統計
-- ============================================================
-- 邦交國+代表處+組織總計
function p.allTotal(frame)
return (tonumber(p.bangTotal(frame)) or 0)
+ (tonumber(p.jingTotal(frame)) or 0)
+ (tonumber(p.orgTotal(frame)) or 0)
end
-- 曾建交總數(現有正式邦交國+歷史邦交國)
function p.everTotal(frame)
return (tonumber(p.bangTotal(frame)) or 0)
+ (tonumber(p.histTotal(frame)) or 0)
end
function p.debug(frame)
local c = getContent()
local has_bang = c:find("id=luminebang") and "有" or "無"
return "頁面長度:" .. #c .. " | luminebang:" .. has_bang
end
return p