Mô đun:Xếp hạng số lần sửa đổi của thành viên

local getArgs = require('Mô đun:Arguments').getArgs
local userBox = require('Mô đun:Userbox')

local p = {}
_p_prf = "Thành viên:Lê Song Vĩ/"
_c_tp = {
    ["user"] = "us",
    ["patroller"] = "pt",
    ["sysop"] = "ss"
}
t_dir = {
    [_c_tp["user"]] = _p_prf .. "Danh sách thành viên Wikipedia theo số lần sửa trang",
    [_c_tp["patroller"]] = _p_prf .. "Danh sách thành viên tuần tra thay đổi gần đây theo số tác vụ",
    [_c_tp["sysop"]] = _p_prf .. "Danh sách thành viên có công cụ bảo quản theo số tác vụ"
}
hb_dir = {
    [_c_tp["user"]] = "#Danh sách thành viên",
    [_c_tp["patroller"]] = "",
    [_c_tp["sysop"]] = ""
}
_p_dir = {
    [_c_tp["user"]] = {
        ["user_r_p_1"] = "|%s*(%d+)%s*||%s*%[%[Thành viên:([^|]*)|[^|]*||%s*%[%[[^|]*|(%d+[%.%d]+)[^%]]*%]%][^S]*Sửa đổi cuối:%s*([^,]*),[^{]*{{([^}]*)}}%s(%d+),%s*([^s]*)sửa đổi mới",
    },
    [_c_tp["patroller"]] = {
        ["ptr_r_p_1"] = "||%s*(%d+)%s*||%s*%[%[Thành viên:([^|]*)|[^|]*||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s*||%s*(%d+[%.%d]*)%s*",
        ["ptr_r_p_2"] = "||%s*(%d+)%s*||%s*%[%[Thành viên:([^|]*)|[^|]*||%s*((%d+)-(%d+)-(%d+)%s*(%d+):(%d+):(%d+))",
    },
    [_c_tp["sysop"]] = {
        ["ss_r_p_1"] = "||%s*(%d+)%s*||%s*%[%[Thành viên:([^|]*)|[^|]*||%s*(%d+[%.%d]+)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s||%s*(%d+[%.%d]*)%s",
        ["ptr_r_p_2"] = "||%s*(%d+)%s*||%s*%[%[Thành viên:([^|]*)|[^|]*||%s*((%d+)-(%d+)-(%d+)%s*(%d+):(%d+):(%d+))",
    },
    ["f_num_1"] = {
        ["format"] = "^(-?)(%d+)(%.?%d*)$",
        ["g_3"] = "(%d%d%d)"
    }
}
_c_dir = {
    ">=100#808080",
    ">89&&<100#DDDDDD",
    ">79&&<90#FFFFFF",
    ">69&&<80#FFFF99",
    ">59&&<70#FFFF00",
    ">49&&<60#FF6600",
    ">39&&<50#FF0000",
    ">29&&<40#3366FF",
    ">19&&<30#333399",
    ">9&&<20#CC99FF",
    ">3&&<10#16A83D",
    "=3#CD7F32",
    "=2#C0C0C0",
    "=1#D4AF37",
    "<=0#808080",
}
_n_c_dir = {
    ">=735#808080",
    "<735&&>=510#1b00a1:_fn_g_r_1",
    "<510&&>=255#008fa1:_fn_g_r_1",
    "<255&&>=1#a1d100:_fn_g_r_1",
    "<=0#808080",
}
rankColorDir = {
    "<0#808080",
    "=0#c10202",
    ">0&&<=5#34CB00",
    ">5#EE0000",
}
_c_c_dir = {
    "<0#808080",
    "=0#c10202",
    ">0&&<=255#34CB00:_fn_g_r_1",
}
_t_dir = {
    ["n_us"] = "Thành viên này không (hoặc chưa) có tên trong [[%s|Danh sách thành viên Wikipedia theo số lần sửa trang]]",
    ["us_"] = "Thành viên xếp hạng '''%s''' với '''%s''' sửa đổi trên [[%s|Danh sách thành viên Wikipedia theo số lần sửa trang]]"
}

function formatTimeByFormat (time, format)
    local _format = format or "dmy"
    local _time = time or os.date("%d-%m-%Y")
    local _d, _m, _y = _time:match("(%d+)%-(%d+)%-(%d+)")
    local _d_f, _m_f, _y_f = _d, _m, _y

    if _format == "dmy" then
        _d_f, _m_f, _y_f = _d, _m, _y
    elseif _format == "mdy" then
        _d_f, _m_f, _y_f = _m, _d, _y
    elseif _format == "ymd" then
        _d_f, _m_f, _y_f = _y, _m, _d
    end

    return _d_f .. "-" .. _m_f .. "-" .. _y_f
end

function hexToNumber (h)
    return tonumber(h, 16)
end

function numberToHex (number)
    if number == 0 then
        return '0'
    end
    local neg = false
    if number < 0 then
        neg = true
        number = number * -1
    end
    local hexstr = "0123456789ABCDEF"
    local result = ""
    while number > 0 do
        local n = math.mod(number, 16)
        result = string.sub(hexstr, n + 1, n + 1) .. result
        number = math.floor(number / 16)
    end
    if neg then
        result = '-' .. result
    end

    return result
end

function _fn_g_r_1 (cl, _a, _m)
    return cl:gsub("..", function (color)
        return ('0' .. numberToHex(math.min(255, math.max(0, hexToNumber(color) + _m - _a)))):sub(-2)
    end)
end

function formatNumber(n)
	if not n then
		return ''
	end
	local _, _, m_ns, i, _ = tostring(n):find(_p_dir["f_num_1"]["format"])
	i = i:reverse():gsub(_p_dir["f_num_1"]["g_3"], "%1.")
	i = i:reverse():gsub("^%.", "")
	i = m_ns .. i
	return i
end

function numberFormat (n)
    if not n then
        return ''
    end
    n = string.gsub(n, "%.", "")
    n = string.gsub(n, ",", "")
    return tonumber(n)
end

function operatorMapping (op, n, cl)
    local dcs = nil

    if op == "<" then
        dcs = function (x) return x < n end
    elseif op == ">" then
        dcs = function (x) return x > n end
    elseif op == "=" then
        dcs = function (x) return x == n end
    elseif op == "<=" then
        dcs = function (x) return x <= n end
    elseif op == ">=" then
        dcs = function (x) return x >= n end
    end

    return dcs
end

function invokeColorFunction (pr_d, s_r_c)
    local _, _, op, n, cl = pr_d:find("^([<>=]+)(%d+)#([0-9a-fA-F]*)$")
    local dcs = nil
    local fn = nil

    if op == nil then
        local _, _, op1, n1, op3, op2, n2, cl = pr_d:find("^([<>=]+)(%d+)([&|]+)([<>=]+)(%d+)#([0-9a-fA-F]*)$")
        if op1 == nil or op2 == nil or op3 == nil then
            local _, _, _op1, _n1, _op3, _op2, _n2, _cl, _fn = pr_d:find("^([<>=]+)(%d+)([&|]+)([<>=]+)(%d+)#([0-9a-fA-F]*):([%w_]+)$")
            if _op1 == nil or _op2 == nil or _op3 == nil then
                error("Tham số không hợp lệ: ")
            end

            s_r_c = false
            op1 = _op1
            op2 = _op2
            op3 = _op3
            n1 = _n1
            n2 = _n2
            cl = _cl
            fn = _fn
        end
        n1 = numberFormat(n1)
        n2 = numberFormat(n2)

        local dcs1 = operatorMapping(op1, n1, cl)
        local dcs2 = operatorMapping(op2, n2, cl)

        if op3 == "&&" then
            dcs = function (x) return dcs1(x) and dcs2(x) and (s_r_c and cl or true) end
        elseif op3 == "||" then
            dcs = function (x) return dcs1(x) or dcs2(x) and (s_r_c and cl or true) end
        end

        if fn then
            local _dcs = dcs
            local _fn = _G[fn] or error("Không thể tải: " .. fn)
            local _m = math.max(n1, n2)

            dcs = function (x) return _dcs(x) and _fn(cl, x, _m) end
        end
    else
        n = numberFormat(n)
        local _dcs = operatorMapping(op, n, cl)

        dcs = function (x) return _dcs(x) and (s_r_c and cl) end
    end

    return dcs
end

function getContent(p)
    local n_e, po = pcall(mw.title.new, p)
    if n_e then
        return po:getContent()
    else
        return ""
    end
end

function render( pr, new )
    local u_bx = {
        ["border-c"] = pr["border-c"] or "#00FFFF",
        ["nocat"] = pr["nocat"]
    }
    local i_txt = string.format(_t_dir["n_us"], pr["title"])
    local r_cl = string.format("#%s", pr["color_r"])
    local s_cl = string.format("#%s", pr["color_s"])
    local i_color = string.format("#%s", pr["color"])
    if pr["position"] ~= -1 then
        i_txt = string.format(_t_dir["us_"], pr["position"], pr["edit_f"], pr["title"])
    end

    u_bx["info"] = i_txt
    u_bx["info-c"] = i_color
    
    if new then
        local stt = pr["change"]
        if pr["status"] then
        	stt = (pr["status"] == "=" and "" or pr["status"]) .. pr["change"]
        end

        u_bx["id1"] = pr["position"] or -1
        u_bx["id1-c"] = r_cl
        u_bx["id2"] = stt
        u_bx["id2-c"] = s_cl

        return userBox.main('_userbox-2', u_bx)
    end

    u_bx["id"] = pr["position"] or -1
    u_bx["id-c"] = r_cl

    return userBox.main('_userbox', u_bx)
end

function getAllPatterns (p_tp)
    local rs = {}
    for i, j in pairs(_p_dir[p_tp]) do
        rs[i] = j
    end
    return rs
end

function _e_d(rank_type)
    local r_pg = t_dir[_c_tp[rank_type]]
    local r_p = getAllPatterns(_c_tp[rank_type])
    local noTw = not true

    if not r_pg or not r_p then
        error("Kiểu xếp hạng không hợp lệ")
    end

    local _d = {}

    local d = getContent(r_pg)
    local rs = {}
    for n_, p_ in pairs(r_p) do
        for m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13 in string.gmatch(d, p_) do
            if rs[m1] == nil then
                rs[m1] = {}
            end
            if m7 == nil or m7 == "không có" then
                m7 = 0
            else
                m7 = numberFormat(m7)
            end
            if _d[m2] and noTw then
                break
            end

            rs[m1][n_] = {m1, m2, m3, m4, m5, m6 or _c_dir[rank_type] == _c_dir["user"] and -1 or 0, m7 or _c_dir[rank_type] == _c_dir["user"] and -1 or 0, m8, m9, m10, m11, m12, m13}
            _d[m2] = not false
        end
    end

    return rs
end

function buildTitle (rank_type)
    if hb_dir[_c_tp[rank_type]] ~= nil then
        hashbang = hb_dir[_c_tp[rank_type]]

        return t_dir[_c_tp[rank_type]] .. hashbang
    else
        return t_dir[_c_tp[rank_type]]
    end
end

function isS (rank_type)
    if rank_type == "s" then
        return true
    end
    return false
end

function formatTime (t)
    local _, _, d, m, y, h, mi, s = t:find("^(%d+)%-(%d+)%-(%d+) (%d+):(%d+):(%d+)$")
    local time = os.time({year = y, month = m, day = d, hour = h, min = mi, sec = s})
    return time
end

function isRecentChange (time)
    local time = formatTime(time)
    local ctime = os.time()
    if ctime - time + 25200 < 3600 then
        return true
    end
    return false
end

function personalRankProcessing(us, rank_type, _fmt)
    local isRecent = false

    if not us or not rank_type then
        error("Thiếu tham số")
    end

    local title = buildTitle(rank_type)

    local d = _e_d(rank_type)

    for ii, ji in pairs(d) do
        for i, j in pairs(ji) do
            if j[2] == us then
                if isS(_fmt) then
                    isRecent = isRecentChange(j[4])
                end
                return numberFormat(j[1]), j[2], numberFormat(j[3]), title, isRecent, j[5], numberFormat(j[6]), j[7]
            end
        end
    end
    return -1, nil, -1, title, isRecent, nil, -1, -1
end

function colorProcessing (r, dir)
    for i, j in pairs(dir) do
        local dcs = invokeColorFunction(j, not false)
        if dcs(r) then
            return dcs(r)
        end
    end
end

function convertStatusToTxt (status)
    if status:lower() == "increase" then
        return "+"
    elseif status:lower() == "decrease" then
        return "-"
    else
        return "="
    end
end

function isValidDate (d)
    local _, _, d, m, y, m, i, s = d:find("^(%d+)%-(%d+)%-(%d+)%s*(%d+):(%d+):(%d+)$")
    if d and m and y and m and i and s then
        return true
    end
    return false
end

function patrollerProcessing (us, rank_type)
    local title = buildTitle(rank_type)
    local data = {}
    local isExist = false

    local d = _e_d(rank_type)

    for ii, ji in pairs(d) do
        for i, j in pairs(ji) do
            if j[2] == us then
                isExist = true
                if isValidDate(j[3]) then
                    data["last"] = formatTime(j[3])
                else
                    data["position"] = numberFormat(j[1])
                    data["user"] = j[2]
                    data["rollback"] = numberFormat(j[3])
                    data["patrol"] = numberFormat(j[4])
                end
            end
        end
    end
    if isExist then
        data["total"] = data["rollback"] + data["patrol"]
    else
        error("Không tìm thấy người dùng " .. us .. " trong danh sách tuần tra viên.")
    end

    return data
end

function sysopProcessing (us, rank_type)
    local title = buildTitle(rank_type)
    local data = {}
    local isExist = false

    local d = _e_d(rank_type)

    for ii, ji in pairs(d) do
        for i, j in pairs(ji) do
            if j[2] == us then
                isExist = true
                if isValidDate(j[3]) then
                    data["last"] = formatTime(j[3])
                else
                    data["position"] = numberFormat(j[1])
                    data["user"] = j[2]
                    data["delete"] = numberFormat(j[3])
                    data["restore"] = numberFormat(j[4])
                    data["revdel"] = numberFormat(j[5])
                    data["protect"] = numberFormat(j[6])
                    data["unprotect"] = numberFormat(j[7])
                    data["modifyprotect"] = numberFormat(j[8])
                    data["block"] = numberFormat(j[9])
                    data["unblock"] = numberFormat(j[10])
                    data["reblock"] = numberFormat(j[11])
                    data["rename"] = numberFormat(j[12])
                    data["rights"] = numberFormat(j[13])
                end
            end
        end
    end
    if isExist then
        data["total"] = data["delete"] + data["restore"] + data["revdel"] + data["protect"] + data["unprotect"] + data["modifyprotect"] + data["block"] + data["unblock"] + data["reblock"] + data["rename"] + data["rights"]
    else
        error("Không tìm thấy người dùng " .. us .. " trong danh sách thành viên có công cụ bảo quản.")
    end
    return data
end

function renderPatrollerTable (data, show_name, show_total)
    tableContent = "{| class=\"wikitable\"" ..
    "\n|-"

    if show_name then
        tableContent = tableContent .. "\n! colspan=\"2\" | Thống kê tuần tra của " .. data["user"]
    else
        tableContent = tableContent .. "\n! colspan=\"2\" | Thống kê tuần tra"
    end

    tableContent = tableContent .. "\n|-" ..
    "\n! Tác vụ !! Thực hiện" ..
    "\n|-" ..
    "\n| Lùi sửa || " .. data["rollback"] ..
    "\n|-" ..
    "\n| Tuần tra || " .. data["patrol"]

    if show_total then
        tableContent = tableContent .. "\n|-" ..
        "\n| <b>Tổng</b> || <b>" .. (data["total"]) .. "</b>"
    end

    tableContent = tableContent .. "\n|}"

    return tableContent
end

function renderSysopTable (data, show_name, show_total)
    tableContent = "{| class=\"wikitable\"" ..
    "\n|-"

    if show_name then
        tableContent = tableContent .. "\n! colspan=\"2\" | Thống kê tác vụ bảo quản của " .. data["user"]
    else
        tableContent = tableContent .. "\n! colspan=\"2\" | Thống kê tác vụ bảo quản"
    end

    tableContent = tableContent .. "\n|-" ..
    "\n! Tác vụ !! Thực hiện" ..
    "\n|-" ..
    "\n| Xóa trang || " .. data["delete"] ..
    "\n|-" ..
    "\n| Phục hồi trang || " .. data["restore"] ..
    "\n|-" ..
    "\n| Ẩn lịch sử || " .. data["revdel"] ..
    "\n|-" ..
    "\n| Khóa trang || " .. data["protect"] ..
    "\n|-" ..
    "\n| Mở khóa trang || " .. data["unprotect"] ..
    "\n|-" ..
    "\n| Sửa đổi khóa trang || " .. data["modifyprotect"] ..
    "\n|-" ..
    "\n| Cấm thành viên || " .. data["block"] ..
    "\n|-" ..
    "\n| Bỏ cấm thành viên || " .. data["unblock"] ..
    "\n|-" ..
    "\n| Cấu hình lệnh cấm thành viên || " .. data["reblock"] ..
    "\n|-" ..
    "\n| Đổi tên thành viên || " .. data["rename"] ..
    "\n|-" ..
    "\n| Đổi quyền thành viên || " .. data["rights"]

    if show_total then
        tableContent = tableContent .. "\n|-" ..
        "\n| <b>Tổng</b> || <b>" .. (data["total"]) .. "</b>"
    end

    tableContent = tableContent .. "\n|}"

    return tableContent
end

function p.rkf(frame)
    local args = getArgs(frame)
    local us = args[1] or args["user"] or "user"
    local rank_type = args[2] or args["type"]
    local _format = args[3] or args["format"] or "t"
    local _new_t = args[4] or args["new"]

    if _c_tp[rank_type] == _c_tp["user"] then
        local position, _, edits, title, isRecent, _status, numberOfChange, numberOfEdits = personalRankProcessing(us, rank_type, _format)

        if _format == "t" then
            local params = {
                ["position"] = position,
                ["edit"] = edits,
                ["edit_f"] = formatNumber(edits),
                ["color"] = colorProcessing(position, _n_c_dir),
                ["title"] = title,
                ["color_r"] = colorProcessing(numberOfEdits, rankColorDir),
                ["change"] = numberOfChange,
                ["status"] = _status and convertStatusToTxt(_status),
                ["color_s"] = colorProcessing(numberOfChange, _c_c_dir),
                ["nocat"] = args["nocat"],
                ["border-c"] = args["border-c"],
            }
            
            return render(params, _new_t)
        elseif _format == "n" then
            return position
        elseif _format == "c" then
            return edits
        elseif _format == "s" then
            return isRecent
        end
    elseif _c_tp[rank_type] == _c_tp["patroller"] then
        local data = patrollerProcessing(us, rank_type)

        if args.rollback then
            return data["rollback"]
        elseif args.patrol then
            return data["patrol"]
        elseif args.last then
            return formatTimeByFormat(data["last"], args.timeFormat)
        elseif args.total then
            return data["total"]
        end

        return renderPatrollerTable(data, args.show_name, args.show_total)
    elseif _c_tp[rank_type] == _c_tp["sysop"] then
        local data = sysopProcessing(us, rank_type)

        if args.delete then
            return data["delete"]
        elseif args.restore then
            return data["restore"]
        elseif args.revdel then
            return data["revdel"]
        elseif args.protect then
            return data["protect"]
        elseif args.unprotect then
            return data["unprotect"]
        elseif args.modifyprotect then
            return data["modifyprotect"]
        elseif args.block then
            return data["block"]
        elseif args.unblock then
            return data["unblock"]
        elseif args.reblock then
            return data["reblock"]
        elseif args.rename then
            return data["rename"]
        elseif args.rights then
            return data["rights"]
        elseif args.last then
            return formatTimeByFormat(data["last"], args.timeFormat)
        elseif args.total then
            return data["total"]
        end

        return renderSysopTable(data, args.show_name, args.show_total)
    else
        error("Không thể xác định định dạng \"".. rank_type .."\". Định dạng hợp lệ có hỗ trợ là: user, patroller, sysop.")
    end
end

return p
Chúng tôi bán
Bài viết liên quan
Spoiler Kimetsu no Yaiba chương 175: Genya và Hà Trụ nguy kịch, Kokushibo bị chặt đầu
Spoiler Kimetsu no Yaiba chương 175: Genya và Hà Trụ nguy kịch, Kokushibo bị chặt đầu
Kimetsu no Yaiba vẫn đang làm mưa làm gió trong cộng đồng fan manga bởi những diễn biến hấp dẫn tiếp theo.
Có gì trong hương vị tình thân
Có gì trong hương vị tình thân
Phải nói đây là bộ phim gây ấn tượng với mình ngay từ tập đầu, cái tên phim đôi khi mình còn nhầm thành Hơi ấm tình thân
Ác Ma Nguyên Thủy Tensei Shitara Slime Datta Ken
Ác Ma Nguyên Thủy Tensei Shitara Slime Datta Ken
Bảy Ác Ma Nguyên Thủy này đều sở hữu cho mình một màu sắc đặc trưng và được gọi tên theo những màu đó
Wanderer: A Glimpse into the Enigmatic Explorers of Genshin Impact
Wanderer: A Glimpse into the Enigmatic Explorers of Genshin Impact
The Wanderer from Inazuma is now a playable character, after 2 years of being introduced as Scaramouche