Module:Sandbox/Vergir: Difference between revisions

Vergir (talk | contribs)
Audit script v2: normalize underscores, check target existence, group by change (with help from vergir-bot LLM)
Audit script v3: formatted label values + classification column (with help from vergir-bot LLM)
Line 2: Line 2:
-- with attribute styling enabled (Passive/Active Main stats), compute the
-- with attribute styling enabled (Passive/Active Main stats), compute the
-- label link target under the CURRENT priority (attr link > StatLinks)
-- label link target under the CURRENT priority (attr link > StatLinks)
-- and the PROPOSED priority (StatLinks > attr link) and list the results.
-- and the PROPOSED priority (StatLinks > attr link), and classify the change.
local p = {}
local p = {}
local lang = require "Module:Lang"
local lang = require "Module:Lang"
Line 11: Line 11:
local LABEL_KEY_REMAP = { DotDuration = "DOTDuration" }
local LABEL_KEY_REMAP = { DotDuration = "DOTDuration" }
local IGNORED = { BuildUpPerShot = true }
local IGNORED = { BuildUpPerShot = true }
-- Keys whose StatLinks entry is worse than the current type link.
-- Proposed StatLinks fix noted alongside.
local STATLINKS_FIX = {
    SlowPercent = "Movement Slow",
    MaxSlowPercent = "Movement Slow",
}
local DEBATABLE = {
    GroundDashReductionPercent = true,
}


local function get_pair(base, s1, s2)
local function get_pair(base, s1, s2)
Line 30: Line 40:
end
end


local exists_cache = {}
-- Resolve a title through one redirect hop; returns final page name
local function page_status(t)
local resolve_cache = {}
     if t == nil then return "" end
local function resolve(t)
     if exists_cache[t] == nil then
     if t == nil then return nil end
     if resolve_cache[t] == nil then
         local title = mw.title.new(t)
         local title = mw.title.new(t)
         if not title or not title.exists then
        local r = t
            exists_cache[t] = "'''MISSING'''"
         if title and title.exists and title.isRedirect then
        elseif title.isRedirect then
             local tgt = title.redirectTarget
             local target = title.redirectTarget
             if tgt then r = tgt.prefixedText end
             exists_cache[t] = "redirect → " .. (target and target.prefixedText or "?")
         elseif not title or not title.exists then
         else
             r = t .. " (MISSING)"
             exists_cache[t] = "ok"
         end
         end
        resolve_cache[t] = r
     end
     end
     return exists_cache[t]
     return resolve_cache[t]
end
 
local function fmt_value(label_key, value, label)
    local n = tonumber(tostring(value):match("^-?%d+%.?%d*"))
    if not n then return label end
    local prefix = get_pair(label_key, "_prefix", "_Prefix")
    local postfix = get_pair(label_key, "_postfix", "_Postfix")
    if prefix == "{s:sign}" then prefix = n >= 0 and "+" or "" end
    local s = tostring(n)
    if prefix ~= "" then s = prefix .. s end
    if postfix ~= "" then s = s .. (postfix == "HP/s" and " " or "") .. postfix end
    return s .. " " .. label
end
end


function p.audit(frame)
function p.audit(frame)
    local mode = frame.args[1] or "diff" -- "diff" | "all"
    local rows = {}
     local names = {}
     local names = {}
     for key, item in pairs(data) do
     for key, item in pairs(data) do
Line 58: Line 79:
     end)
     end)


     local n_items, n_stats, n_same, n_diff = 0, 0, 0, 0
    local rows = {}
    local by_change = {} -- "cur → new" -> list of "Item (Label)"
    local counts = {}
     local n_items, n_stats, n_same = 0, 0, 0
     for _, key in ipairs(names) do
     for _, key in ipairs(names) do
         local item = data[key]
         local item = data[key]
Line 81: Line 103:
                             local cur = attr_link or sl
                             local cur = attr_link or sl
                             local new = sl or attr_link
                             local new = sl or attr_link
                             local differs = (cur or "") ~= (new or "")
                             if (cur or "") == (new or "") then
                            if differs then
                                 n_same = n_same + 1
                                 n_diff = n_diff + 1
                                local k = (cur or "(none)") .. " → " .. (new or "(none)")
                                by_change[k] = by_change[k] or { cur = cur, new = new, list = {} }
                                table.insert(by_change[k].list,
                                    string.format("[[%s]] (%s)", item.Name or key, label))
                             else
                             else
                                 n_same = n_same + 1
                                 local kind
                            end
                                if STATLINKS_FIX[label_key] then
                            if mode == "all" or differs then
                                    kind = "Regression → fixed via StatLinks (" .. label_key .. " = " .. STATLINKS_FIX[label_key] .. ")"
                                elseif DEBATABLE[label_key] then
                                    kind = "Debatable"
                                elseif resolve(cur) == resolve(new) then
                                    kind = "NOP (redirect to same page)"
                                else
                                    kind = "Fix"
                                end
                                counts[kind] = (counts[kind] or 0) + 1
                                 table.insert(rows, string.format(
                                 table.insert(rows, string.format(
                                     "|-%s\n| [[%s]] || %s || %s || %s || %s || %s || %s",
                                     "|-\n| [[%s]] || %s || [[%s]] || [[%s]] || %s",
                                    differs and ' style="background:#4a3a1a"' or "",
                                     item.Name or key, fmt_value(label_key, obj.Value, label),
                                     item.Name or key, tostring(sec.Type), label_key, tostring(obj.Type),
                                     cur or "", new or "", kind))
                                     label, cur or "''(none)''", new or "''(none)''"))
                             end
                             end
                         end
                         end
Line 108: Line 132:
     local out = {}
     local out = {}
     table.insert(out, string.format(
     table.insert(out, string.format(
         "Items scanned: %d. Passive/Active main stats with a label: %d. Unchanged: %d. Link changes: %d.\n",
         "Items scanned: %d. Passive/Active main stats with a label: %d. Unchanged: %d. Changed: %d.\n",
         n_items, n_stats, n_same, n_diff))
         n_items, n_stats, n_same, #rows))
 
     local ks = {}
    -- Grouped summary
     for k in pairs(counts) do table.insert(ks, k) end
    table.insert(out, "== Grouped by change ==")
     table.sort(ks)
     local keys = {}
     for _, k in ipairs(ks) do table.insert(out, string.format("* %s: %d", k, counts[k])) end
     for k in pairs(by_change) do table.insert(keys, k) end
     table.insert(out, '{| class="wikitable sortable"\n! Item !! Label !! Current target !! Proposed target !! Type')
     table.sort(keys)
    table.insert(out, '{| class="wikitable sortable"\n! Current link !! Status !! Proposed link !! Status !! # !! Items (label)')
     for _, k in ipairs(keys) do
        local g = by_change[k]
        table.insert(out, string.format("|-\n| [[%s]] || %s || [[%s]] || %s || %d || %s",
            g.cur or "", page_status(g.cur), g.new or "", page_status(g.new),
            #g.list, table.concat(g.list, ", ")))
    end
    table.insert(out, "|}")
 
    -- Full row table
    table.insert(out, "== Per stat ==")
     table.insert(out, '{| class="wikitable sortable"\n! Item !! Section !! Stat key !! Type !! Label !! Current link !! Proposed link')
     for _, r in ipairs(rows) do table.insert(out, r) end
     for _, r in ipairs(rows) do table.insert(out, r) end
     table.insert(out, "|}")
     table.insert(out, "|}")