local luaq = require("Module:Luaq") local module = {} local getArgs = require("Module:Arguments").getArgs -- 从UserGroup模块获取所有萌娘百科维护组成员的用户名 function module._get_userlist(js) local _user_mod = require(tostring(mw.title.new("Module:UserGroup"))) local users = _user_mod.enumerate('') local hash_users = {} if js ~= nil then return mw.text.jsonEncode(users) end for _, u in ipairs(users) do hash_users[u] = false end return hash_users end -- 根据filter获取每个用户组的人数,filter的定义参考UserGroup模块 function module._get_usercount(f) local _user_mod = require(tostring(mw.title.new("Module:UserGroup"))) local users = _user_mod.enumerate(f) return #users end -- 计数函数 function module._count(content) local count_table = {["管理员"] = {},["巡查姬"] = {}, ["自动确认用户"] = {}, voted = {}, error = {}} local role = "" local vote = "" if content ~= nil then local vote_area = mw.text.split(content,"==(=?)(%s+)投票区(.-)==(=?)\n") -- 找到最后一个投票区开始计数 vote_area = vote_area[#vote_area] for line in mw.text.gsplit(vote_area, "\n") do -- 按行处理每一个可能的投票内容 -- 根据小标题判断投票归类于哪一个用户组 if mw.ustring.find(line, "===(=?)(%s*)管理员(.-)===(=?)") then role = "管理员" elseif mw.ustring.find(line, "===(=?)(%s*)巡查姬(.-)===(=?)") then role = "巡查姬" elseif mw.ustring.find(line, "===(=?)(%s*)参与讨论的自动确认用户(%s*)===(=?)") then role = "自动确认用户" elseif mw.ustring.find(line, "===(=?)(%s*)无票权用户意见(%s*)===(=?)") then break else --[[local patterns = { '%[%[%s*[Uu][Ss][Ee][Rr]%s*:([^|%]/\\]+)%]%]', '%[%[%s*[Uu][Ss][Ee][Rr]%s*:([^|%]/\\]+)|.-%]%]', '%[%[%s*[Uu]%s*:([^|%]/\\]+)|.-%]%]', '%[%[%s*:[Uu][Ss][Ee][Rr]%s*:([^|%]/\\]+)%]%]', '%[%[%s*:[Uu][Ss][Ee][Rr]%s*:([^|%]/\\]+)|.-%]%]', '%[%[%s*:[Uu]%s*:([^|%]/\\]+)|.-%]%]', }]]-- --[[for _, p in ipairs(patterns) do username = mw.ustring.match(line, p) if username ~= nil then break end end]]-- -- 根据投票前的投票模板判断当前投票 if mw.ustring.find(line, "{{同意}}") then vote = "同意" elseif mw.ustring.find(line, "{{反对}}") then vote = "反对" elseif mw.ustring.find(line, "{{弃权}}") then vote = "弃权" end -- 去除用删除线删去的投票 local del_pattern = {".*<del>.*</del>$",".*<s>.*</s>"} if line == "" then elseif mw.ustring.match(line, del_pattern[1]) or mw.ustring.match(line, del_pattern[2]) then else -- 使用Sig2User模块获取投票人的用户名 local frame = mw.getCurrentFrame() local username = frame:callParserFunction{name="#invoke:Sig2User",args={"main", line, suppress="nil"}} -- 如果出现解析错误则放入count_table["error"]表中等待人工判断 if username == "Error: Invalid signature" then table.insert(count_table["error"], line) else -- 否则将投票人的用户名存入count_table中 if count_table[role] == nil then count_table[role] = {} end if count_table[role][vote] == nil then count_table[role][vote] = {} end table.insert(count_table[role][vote], username) table.insert(count_table["voted"], username) end end end end end return count_table end -- 包装frame:expandTemplate函数,如果expand为false则直接返回模板 function module._expandTemplate(frame, template, expand) if expand then return frame:expandTemplate{title=template} else return "{{"..template.."}}" end end function module.main(frame) local args = getArgs(frame) title = args["title"] local users = module._get_userlist() local parent = frame:getParent() local caller = nil local expand = true -- 如果title参数为nil则获取当前frame的父frame的title if title == nil then caller = parent:getTitle() else -- 否则使用title参数内容 caller = title expand = false end -- 获取上一步中title的内容 local content = mw.title.new(caller):getContent() local count_table = module._count(content) -- 将count_table["voted"]表中的内容和所有萌百维护组用户名一一比对,标记所有投票的维护组成员 for _, v in ipairs(count_table["voted"]) do if users[v] ~= nil then users[v] = true end end -- 过滤出所有没有投票的维护组成员 local filtered = luaq.asQuery(users):where(function(_,_,v) return v==false end):query() local not_voted = "" local not_voted_count = 0 for _ , v in ipairs(filtered) do not_voted = not_voted .. v .. ", " not_voted_count = not_voted_count + 1 end -- 计算有多少自动确认用户投票,假设所有投票的自动确认用户都有票权 local ac_users = 0 for _, v in pairs(count_table["自动确认用户"]) do if v ~= nil then ac_users = ac_users + #v end end -- 拼接结果字符串 local vote_result = "投票开始时共有".. module._get_usercount('s') .."名参与站务的管理员;其中,".. "\n" .. "*'''".. #(count_table["管理员"]["同意"] or {}) .."'''人"..module._expandTemplate(parent,"同意",expand).. "\n" .. "*'''".. #(count_table["管理员"]["反对"] or {}) .."'''人"..module._expandTemplate(parent,"反对",expand).. "\n" .. "*'''".. #(count_table["管理员"]["弃权"] or {}) .."'''人"..module._expandTemplate(parent,"弃权",expand).. "\n" .. "投票开始时共有".. module._get_usercount('p') .. "名正式巡查姬;其中,".. "\n" .. "*'''".. #(count_table["巡查姬"]["同意"] or {}) .."'''人"..module._expandTemplate(parent,"同意",expand).. "\n" .. "*'''".. #(count_table["巡查姬"]["反对"] or {}) .."'''人"..module._expandTemplate(parent,"反对",expand).. "\n" .. "*'''".. #(count_table["巡查姬"]["弃权"] or {}) .."'''人"..module._expandTemplate(parent,"弃权",expand).. "\n" .. "共有".. ac_users .. "名有票权的自动确认用户参与了投票;其中".. "\n" .. "*'''".. #(count_table["自动确认用户"]["同意"] or {}) .."'''人"..module._expandTemplate(parent,"同意",expand).. "\n" .. "*'''".. #(count_table["自动确认用户"]["反对"] or {}) .."'''人"..module._expandTemplate(parent,"反对",expand).. "\n" .. "*'''".. #(count_table["自动确认用户"]["弃权"] or {}) .."'''人"..module._expandTemplate(parent,"弃权",expand).. "\n" .. "共有".. not_voted_count .."人没有参与投票(".. string.sub(not_voted,0, #not_voted-2) ..")".. "<hr/>".. "----对"..caller.."的自动计票结束,请人工复核后发布----" .. "\n" -- 如果error表中有值则打印error表内容 -- 由于目前_count函数不会处理====同意====这类小标题,error表会一直有值 -- TODO: 处理小标题和模板进入error表的问题 if #count_table["error"] ~= 0 then vote_result = vote_result .. "以下签名无法解析,请手动添加" .. "\n" .. mw.dumpObject(count_table["error"]) end return vote_result end return module