Mudanças entre as edições de "Módulo:Gb"

De Wiki Gla
Ir para navegação Ir para pesquisar
 
(47 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
local p = {}
local p = {}


-- === Utilidades ===
function p.main(frame)
    local args = frame:getParent().args


local function trim(s)
    local normal_nivel    = mw.text.trim(args['normal_nivel']    or '140')
     if type(s) ~= "string" then
     local normal_equip    = mw.text.trim(args['normal_equip']    or 'Set +8')
        return s
     local hard_personagem = mw.text.trim(args['hard_personagem'] or 'personagem 4 ou 5 estrelas (Diamante)')
     end
     local hard_equip      = mw.text.trim(args['hard_equip']      or 'Set +16')
     return mw.text.trim(s)
end


local function split_list(s)
     local root = mw.html.create('div')
    -- Tenta primeiro por ';' (recomendado quando usar vírgula decimal).
     root:addClass('gb-wrap')
     if s:find(";") then
        local t = {}
        for part in mw.text.gsplit(s, ";", true) do
            table.insert(t, part)
        end
        return t
    end
    -- Caso não haja ';', separa por ',' (útil se números usam ponto decimal).
     local t = {}
    for part in mw.text.gsplit(s, ",", true) do
        table.insert(t, part)
    end
    return t
end


local function parse_number(token)
    -- CSS via TemplateStyles (recomendado) ou inline
     if type(token) ~= "string" then
     -- Botões (tabs)
        return nil
     local btns = root:tag('div'):addClass('gb-btns')
     end
    token = trim(token)
    if token == "" then
        return nil
    end


     -- Remove espaços
     btns:tag('button')
    token = token:gsub("%s+", "")
        :addClass('gb-btn'):addClass('active')
        :attr('onclick', "gbSwitch('n',this)")
        :wikitext('Normal ')
        :tag('span'):addClass('gb-badge'):addClass('badge-n')
        :wikitext('Nível ' .. normal_nivel)


     -- Heurística pt-BR:
     btns:tag('button')
    -- 1) Se tiver vírgula e ponto, assume '.' como milhar e ',' como decimal
        :addClass('gb-btn')
    --    Ex.: "1.234,56" -> "1234.56"
        :attr('onclick', "gbSwitch('h',this)")
    if token:find(",") and token:find("%.") then
         :wikitext('Hard ')
         token = token:gsub("%.", "") -- tira milhares
         :tag('span'):addClass('gb-badge'):addClass('badge-h')
         token = token:gsub(",", ".") -- vírgula -> ponto decimal
         :wikitext(hard_equip)
        -- 2) Se só tiver vírgula, assume vírgula decimal
    elseif token:find(",") then
         token = token:gsub(",", ".")
        -- 3) Se só tiver ponto, deixa como está (ponto decimal)
    end


     local n = tonumber(token)
    -- Painel Normal
     return n
     local pn = root:tag('div'):addClass('gb-panel'):addClass('active'):attr('id', 'gbpanel-n')
end
    pn:tag('div'):addClass('gb-title'):wikitext('Requisitos — Normal')
    local ln = pn:tag('ul'):addClass('gb-list')
    ln:tag('li')
        :tag('span'):addClass('gb-dot'):addClass('dot-n'):done()
        :tag('span'):wikitext('Nível mínimo: '):tag('b'):wikitext(normal_nivel)
     ln:tag('li')
        :tag('span'):addClass('gb-dot'):addClass('dot-n'):done()
        :tag('span'):wikitext('Equipamento recomendado: '):tag('b'):wikitext(normal_equip)


local function collect_numbers(frame)
    -- Painel Hard
     local args = frame:getParent() and frame:getParent().args or frame.args
    local ph = root:tag('div'):addClass('gb-panel'):attr('id', 'gbpanel-h')
     local nums = {}
    ph:tag('div'):addClass('gb-title'):wikitext('Requisitos — Hard')
     local lh = ph:tag('ul'):addClass('gb-list')
     lh:tag('li')
        :tag('span'):addClass('gb-dot'):addClass('dot-h'):done()
        :tag('span'):wikitext('Recomendado utilizar um '):tag('b'):wikitext(hard_personagem)
    lh:tag('li')
        :tag('span'):addClass('gb-dot'):addClass('dot-h'):done()
        :tag('span'):wikitext('Equipamento recomendado: '):tag('b'):wikitext(hard_equip)


     -- 1) Lista em 'valores='
     -- Script
     local lista = args.valores or args.lista
     local script = mw.html.create('script')
     if lista and trim(lista) ~= "" then
     script:wikitext([[
        for _, part in ipairs(split_list(lista)) do
function gbSwitch(tab,btn){
            local n = parse_number(part)
['n','h'].forEach(function(t){document.getElementById('gbpanel-'+t).classList.remove('active');});
            if n then
document.querySelectorAll('.gb-btn').forEach(function(b){b.classList.remove('active');});
                table.insert(nums, n)
document.getElementById('gbpanel-'+tab).classList.add('active');
            end
btn.classList.add('active');
        end
}]])
    end


     -- 2) Parâmetros posicionais 1,2,3,...
     -- CSS inline
     local i = 1
     local style = mw.html.create('style')
     while true do
     style:wikitext([[
        local v = args[i]
.gb-wrap{font-family:sans-serif;max-width:600px}
        if v == nil then
.gb-btns{display:flex;border-bottom:2px solid #a2a9b1;margin-bottom:0}
            break
.gb-btn{padding:8px 22px;font-size:14px;font-weight:bold;color:#54595d;background:transparent;border:none;border-bottom:3px solid transparent;margin-bottom:-2px;cursor:pointer;display:flex;align-items:center;gap:6px}
        end
.gb-btn:hover{color:#202122}
        v = trim(v)
.gb-btn.active{color:#202122;border-bottom-color:#3680b0}
        if v and v ~= "" then
.gb-badge{font-size:11px;padding:2px 8px;border-radius:20px;font-weight:bold}
            -- Pode ser lista dentro do posicional
.badge-n{background:#ddeeff;color:#185FA5}
            local parts = split_list(v)
.badge-h{background:#fce8e8;color:#a32d2d}
            for _, part in ipairs(parts) do
.gb-panel{display:none;padding:14px 2px}
                local n = parse_number(part)
.gb-panel.active{display:block}
                if n then
.gb-title{font-size:11px;font-weight:bold;color:#72777d;text-transform:uppercase;letter-spacing:.06em;margin-bottom:10px}
                    table.insert(nums, n)
.gb-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:8px}
                end
.gb-list li{display:flex;align-items:flex-start;gap:8px;font-size:14px;color:#202122;line-height:1.5}
            end
.gb-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;margin-top:5px}
        end
.dot-n{background:#3680b0}
        i = i + 1
.dot-h{background:#e24b4a}
    end
@media(max-width:480px){.gb-btn{padding:8px 14px;font-size:13px}}]])


     return nums
     return tostring(style) .. tostring(root) .. tostring(script)
end
 
local function round(n, casas)
    if not casas or casas == "" then
        return n
    end
    casas = tonumber(casas) or 0
    local mult = 10 ^ casas
    if n >= 0 then
        return math.floor(n * mult + 0.5) / mult
    else
        return math.ceil(n * mult - 0.5) / mult
    end
end
 
local function format_number(n, casas, formato)
    n = round(n, casas)
    if formato == "pt" then
        -- Formata com vírgula decimal e ponto de milhar
        local s = string.format("%." .. tostring(tonumber(casas) or 0) .. "f", n)
        -- s usa ponto decimal; converter para pt-BR
        local inteiro, frac = s:match("^(-?%d+)%.(%d+)$")
        if not inteiro then
            inteiro = s
            frac = nil
        end
        -- insere pontos nos milhares
        local k
        local sign = ""
        if inteiro:sub(1, 1) == "-" then
            sign = "-"
            inteiro = inteiro:sub(2)
        end
        while true do
            inteiro, k = inteiro:gsub("^(-?%d+)(%d%d%d)", "%1.%2")
            if k == 0 then
                break
            end
        end
        if frac then
            return sign .. inteiro .. "," .. frac
        else
            return sign .. inteiro
        end
    else
        -- "en" ou padrão: ponto decimal, sem milhar
        local casasN = tonumber(casas) or 0
        return string.format("%." .. tostring(casasN) .. "f", n)
    end
end
 
local function compute(nums, op)
    if #nums == 0 then
        return nil
    end
    if op == "soma" or op == "sum" then
        local s = 0
        for _, v in ipairs(nums) do
            s = s + v
        end
        return s
    elseif op == "media" or op == "média" or op == "avg" then
        local s = 0
        for _, v in ipairs(nums) do
            s = s + v
        end
        return s / #nums
    elseif op == "min" or op == "mín" then
        local m = nums[1]
        for i = 2, #nums do
            if nums[i] < m then
                m = nums[i]
            end
        end
        return m
    elseif op == "max" then
        local m = nums[1]
        for i = 2, #nums do
            if nums[i] > m then
                m = nums[i]
            end
        end
        return m
    elseif op == "contar" or op == "count" then
        return #nums
    else
        -- padrão: soma
        local s = 0
        for _, v in ipairs(nums) do
            s = s + v
        end
        return s
    end
end
 
-- === Interface pública ===
 
function p.calc(frame)
    local args = frame:getParent() and frame:getParent().args or frame.args
 
    local op = (args.op or args.operacao or args.operacao or "soma"):lower()
    local casas = args.casas or args.decimais or 2
    local formato = (args.formato or args.locale or "pt"):lower() -- "pt" ou "en"
 
    local nums = collect_numbers(frame)
    local result = compute(nums, op)
 
    if result == nil then
        return "—" -- sem dados
    end
 
    return format_number(result, casas, formato)
end
end


return p
return p

Edição atual tal como às 04h47min de 17 de março de 2026

A documentação para este módulo pode ser criada em Módulo:Gb/doc

local p = {}

function p.main(frame)
    local args = frame:getParent().args

    local normal_nivel    = mw.text.trim(args['normal_nivel']    or '140')
    local normal_equip    = mw.text.trim(args['normal_equip']    or 'Set +8')
    local hard_personagem = mw.text.trim(args['hard_personagem'] or 'personagem 4 ou 5 estrelas (Diamante)')
    local hard_equip      = mw.text.trim(args['hard_equip']      or 'Set +16')

    local root = mw.html.create('div')
    root:addClass('gb-wrap')

    -- CSS via TemplateStyles (recomendado) ou inline
    -- Botões (tabs)
    local btns = root:tag('div'):addClass('gb-btns')

    btns:tag('button')
        :addClass('gb-btn'):addClass('active')
        :attr('onclick', "gbSwitch('n',this)")
        :wikitext('Normal ')
        :tag('span'):addClass('gb-badge'):addClass('badge-n')
        :wikitext('Nível ' .. normal_nivel)

    btns:tag('button')
        :addClass('gb-btn')
        :attr('onclick', "gbSwitch('h',this)")
        :wikitext('Hard ')
        :tag('span'):addClass('gb-badge'):addClass('badge-h')
        :wikitext(hard_equip)

    -- Painel Normal
    local pn = root:tag('div'):addClass('gb-panel'):addClass('active'):attr('id', 'gbpanel-n')
    pn:tag('div'):addClass('gb-title'):wikitext('Requisitos — Normal')
    local ln = pn:tag('ul'):addClass('gb-list')
    ln:tag('li')
        :tag('span'):addClass('gb-dot'):addClass('dot-n'):done()
        :tag('span'):wikitext('Nível mínimo: '):tag('b'):wikitext(normal_nivel)
    ln:tag('li')
        :tag('span'):addClass('gb-dot'):addClass('dot-n'):done()
        :tag('span'):wikitext('Equipamento recomendado: '):tag('b'):wikitext(normal_equip)

    -- Painel Hard
    local ph = root:tag('div'):addClass('gb-panel'):attr('id', 'gbpanel-h')
    ph:tag('div'):addClass('gb-title'):wikitext('Requisitos — Hard')
    local lh = ph:tag('ul'):addClass('gb-list')
    lh:tag('li')
        :tag('span'):addClass('gb-dot'):addClass('dot-h'):done()
        :tag('span'):wikitext('Recomendado utilizar um '):tag('b'):wikitext(hard_personagem)
    lh:tag('li')
        :tag('span'):addClass('gb-dot'):addClass('dot-h'):done()
        :tag('span'):wikitext('Equipamento recomendado: '):tag('b'):wikitext(hard_equip)

    -- Script
    local script = mw.html.create('script')
    script:wikitext([[
function gbSwitch(tab,btn){
['n','h'].forEach(function(t){document.getElementById('gbpanel-'+t).classList.remove('active');});
document.querySelectorAll('.gb-btn').forEach(function(b){b.classList.remove('active');});
document.getElementById('gbpanel-'+tab).classList.add('active');
btn.classList.add('active');
}]])

    -- CSS inline
    local style = mw.html.create('style')
    style:wikitext([[
.gb-wrap{font-family:sans-serif;max-width:600px}
.gb-btns{display:flex;border-bottom:2px solid #a2a9b1;margin-bottom:0}
.gb-btn{padding:8px 22px;font-size:14px;font-weight:bold;color:#54595d;background:transparent;border:none;border-bottom:3px solid transparent;margin-bottom:-2px;cursor:pointer;display:flex;align-items:center;gap:6px}
.gb-btn:hover{color:#202122}
.gb-btn.active{color:#202122;border-bottom-color:#3680b0}
.gb-badge{font-size:11px;padding:2px 8px;border-radius:20px;font-weight:bold}
.badge-n{background:#ddeeff;color:#185FA5}
.badge-h{background:#fce8e8;color:#a32d2d}
.gb-panel{display:none;padding:14px 2px}
.gb-panel.active{display:block}
.gb-title{font-size:11px;font-weight:bold;color:#72777d;text-transform:uppercase;letter-spacing:.06em;margin-bottom:10px}
.gb-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:8px}
.gb-list li{display:flex;align-items:flex-start;gap:8px;font-size:14px;color:#202122;line-height:1.5}
.gb-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;margin-top:5px}
.dot-n{background:#3680b0}
.dot-h{background:#e24b4a}
@media(max-width:480px){.gb-btn{padding:8px 14px;font-size:13px}}]])

    return tostring(style) .. tostring(root) .. tostring(script)
end

return p