跳转到内容

模組: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