模組:Recent RfX
外观
local p = {}
local mError = {}
-- lazy load
setmetatable(mError, {
__index = function (_t, k)
local _mError = require('Module:Error')
mError = _mError
return _mError[k]
end
})
local mIfexist = {}
-- lazy load
setmetatable(mIfexist, {
__index = function (_t, k)
local _mIfexist = require('Module:Ifexist')
mIfexist = _mIfexist
return _mIfexist[k]
end
})
-- 註:請不要嘗試使用這裡的常量當參數,不保證不會有奇怪行為
local DEFAULT = '#default'
local UNKNOWN = '#unknown'
local TBA = '#TBA'
local function if_dismissal_vote(val_then, val_else)
return function (type_key)
-- da: 一般解任
-- in: 不活躍解任
if type_key == 'da' or type_key == 'in' then
return val_then
end
return val_else
end
end
local data = {
types = {
a = {
key = 'a',
name = '管理员',
prefix = 'Wikipedia:申请成为管理员',
},
b = {
key = 'b',
name = '行政员',
prefix = 'Wikipedia:申请成为行政员',
},
c = {
key = 'c',
name = '用户查核员',
prefix = 'Wikipedia:申请成为用户查核员',
},
i = {
key = 'i',
name = '-{zh-hans:界面管理员;zh-hant:介面管理員}-',
prefix = 'Wikipedia:申请成为界面管理员',
},
o = {
key = 'o',
name = '监督员',
prefix = 'Wikipedia:申请成为监督员',
},
da = {
key = 'da',
name = '解任',
prefix = 'Wikipedia:管理員解任投票',
},
['in'] = {
key = 'in',
name = '不活跃解任',
prefix = 'Wikipedia:管理員解任投票',
},
[DEFAULT] = 'a',
},
status = {
s = { is_pass = true, bg = '#e0ffe0', status = if_dismissal_vote('-{zh-hans:通过; zh-hant:通過}-(解任)', '通過'), },
tmp = { is_pass = true, bg = '#ffffe0', status = '通過(臨時)', },
nn = { status = '[[Wikipedia:為時尚早|為時尚早]]', },
sn = { status = '[[Wikipedia:雪球法则|雪球法则]]', },
w = { status = if_dismissal_vote('无效', '取消'), },
us = { status = if_dismissal_vote('不-{zh-hans:通过; zh-hant:通過}-(留任)', '不-{zh-hans:通过; zh-hant:通過}-'), },
nc = { status = '无共识', },
ee = { bg = '#ffe0e0', status = '緊急除權', },
ne = { bg = '#ffffe0', status = '未执行', },
fr = { is_tba = true, bg = '#ddddff', status = '凍結', },
un = { bg = '#333333', status = '未知', },
['通过'] = 's',
['通過'] = 's',
['临时'] = 'tmp',
['臨時'] = 'tmp',
['为时尚早'] = 'nn',
['為時尚早'] = 'nn',
['雪球法则'] = 'sn',
['雪球法則'] = 'sn',
['无效'] = 'w',
['無效'] = 'w',
['取消'] = 'w',
['未通过'] = 'us',
['未通過'] = 'us',
['无共识'] = 'nc',
['無共識'] = 'nc',
['紧急除权'] = 'ee',
['緊急除權'] = 'ee',
['未执行'] = 'ne',
['未執行'] = 'ne',
['冻结'] = 'fr',
['凍結'] = 'fr',
[UNKNOWN] = 'un',
[DEFAULT] = nil,
},
specials = {
unknown = {
text = '待考證',
},
tba = {
-- [[Template:TBA]]
bg = '#ddddff',
text = '待公布',
}
}
}
local function get_argument(args, required, keys)
local val
for _, key in ipairs(keys) do
val = args[key]
if val ~= nil and val ~= '' then
return val
end
end
if required then
error(string.format('argument %s missing.', keys[1]))
end
end
local function travel_get_val(t, n)
if t[n] == nil then
return t[DEFAULT]
end
local val = t[n]
if type(val) == type('') then
-- alias
val = t[val]
end
if type(val) ~= type({}) then
error(string.format('Fail to map value, get "%s" return type "%s".', n, type(val)))
end
return val
end
local function check_bad_number_or_wp_50(num, use_wp50_link)
if num ~= '?' and num ~= TBA then
local val = tonumber(num)
if not val then
return mError.error(string.format('<code>%s</code>是一個無法識別的數字。', num))
end
if val > 50 and use_wp50_link then
return string.format('[[WP:50|%d]]', val)
end
return tostring(num)
end
return TBA
end
local function get_support_rate(support, oppose)
support = tonumber(support)
oppose = tonumber(oppose)
if support == nil or oppose == nil then
return TBA
end
if support == 0 then
return '0'
elseif oppose == 0 then
return '100.0'
else
return string.format('%.1f', math.floor((support / (support + oppose) * 100) * 10) / 10) -- math.floor((... * 10) / 10) 截斷在小數點第一位
end
end
local function make_td(bg, text)
local css_text = 'vertical-align: middle; text-align: center;'
if bg then
css_text = string.format('%s background-color: %s;', css_text, bg)
return string.format('| class="skin-invert" style="%s" | %s', css_text, text)
end
return string.format('| style="%s" | %s', css_text, text)
end
local function make_number_td(bg, text)
if text == TBA then
bg = data.specials.tba.bg
text = data.specials.tba.text
end
return make_td(bg, text)
end
function p.main(frame)
local args = frame.args.parent and (frame:getParent() and frame:getParent().args or {}) or frame.args
local output = { '', '|-' }
local apply_type = get_argument(args, true, {'type', '1', 1})
local user = mw.title.new(get_argument(args, true, {'user', '2', 2}), 2).text
local apply_nth = get_argument(args, false, {'nth', '3', 3}) or '1'
local vote_enddate = get_argument(args, false, {'end', '4', 4}) or UNKNOWN
local support = get_argument(args, false, {'support', '5', 5}) or TBA
local oppose = get_argument(args, false, {'oppose', '6', 6}) or TBA
local neutral = get_argument(args, false, {'neutral', '7', 7}) or TBA
local result = get_argument(args, false, {'result', '8', 8}) or UNKNOWN
local extra = get_argument(args, false, {'extra', '9', 9}) or ''
local display_result = get_argument(args, false, {'display-result'}) -- 覆蓋 result 的顯示文字(雖然 result 也可以傳自訂值,不過就失去自動分類的功能了)
-- [新RfX應該使用正確的用戶名當子頁面而非使用下方參數]
local nick_override = get_argument(args, false, {'nick'}) -- 覆蓋連結到RfX頁面的暱稱(僅供存檔使用)
local apply_page_override = get_argument(args, false, {'page'}) -- 覆蓋投票頁面(僅供存檔使用;此參數會干擾 nth_flag 的顯示,如果可以請指定 nick 而非此參數)
local at = travel_get_val(data.types, mw.ustring.lower(apply_type))
local rs = travel_get_val(data.status, mw.ustring.lower(result)) or { status = result }
local status = display_result or rs.status
if type(status) == type(travel_get_val) then
status = status(at.key)
end
if rs.is_tba then
-- 凍結了當然是 TBA,無論如何直接抹掉全部數字
support = TBA
oppose = TBA
neutral = TBA
end
local bg = rs.bg
local user_page = at.prefix .. '/' .. (nick_override or user)
local user_nth_page = string.format('%s/第%s次', user_page, apply_nth)
local nth_flag = string.format('<sup>%s</sup>', apply_nth)
if apply_nth == '0' then
nth_flag = '' -- 早期第0次貌似被用來代指沒有子頁面後綴的第0次申請(自然而然就不用在用戶名後加數字小標)
elseif apply_nth == '1' and not apply_page_override then
if mIfexist._pfExists(user_nth_page) then
user_page = user_nth_page
else
nth_flag = '' -- no flag for first apply
end
else
user_page = user_nth_page
end
if apply_page_override then
user_page = mw.title.new(apply_page_override).prefixedText -- 早期有部分投票頁有特殊名字
end
table.insert(output, string.format('! scope="row" | [[%s|%s%s]]%s', user_page, user_display_override or user, nth_flag, extra))
table.insert(output, make_td(bg, at.name))
table.insert(output, make_td(bg, rs.is_pass and string.format('\'\'\'%s\'\'\'', status) or status))
table.insert(output, make_td(bg, vote_enddate == UNKNOWN and data.specials.unknown.text or vote_enddate))
table.insert(output, make_number_td(bg, check_bad_number_or_wp_50(support, true)))
table.insert(output, make_number_td(bg, check_bad_number_or_wp_50(oppose, true)))
table.insert(output, make_number_td(bg, check_bad_number_or_wp_50(neutral, false)))
table.insert(output, make_number_td(bg, get_support_rate(support, oppose)))
return table.concat(output, '\n')
end
return p