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

De Wiki Gla
Ir para navegação Ir para pesquisar
 
(43 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
--[[
-- Módulo:BossDisplay (responsivo)
Module:CalculadoraTier


Calculadora de recursos (berry e fragmentos) para evoluir um personagem por Tiers e Estrelas.
local p = {}


✔ Como usar na wiki (Wikitext):
function p.bossInfo(frame)
  {{#invoke:CalculadoraTier|calc
     local args = frame:getParent().args
     |deTier=bronze
    |deEstrelas=2
    |paraTier=diamante
    |paraEstrelas=4
  }}


Parâmetros opcionais:
    local function g(k, default)
  |moeda=berry            -- nome exibido para a moeda (default: "berry")
        return mw.text.trim(args[k] or "") ~= "" and args[k] or default
  |frag=fragmentos       -- nome exibido para os fragmentos (default: "fragmentos")
    end
   |mostrarPassos=sim      -- mostra o passo a passo (sim/não)
 
    local img        = g("img",        "Placeholder.png")
    local nome      = g("nome",      "Nome do Boss")
    local frase      = g("frase",      "Frase ou lema do boss.")
    local hp        = g("hp",        "???")
    local exp        = g("exp",       "???")
    local nivel      = g("nivel",      "???")
    local necessario = g("necessario",    "-")
    local comum      = g("comum",      "")
    local semiraro   = g("semiraro",  "")
    local raro      = g("raro",      "")
    local muitoRaro  = g("muitoraro",  "")
 
    ----------------------------------------------------
    -- CSS responsivo embutido
    ----------------------------------------------------
    local css = [[


📌 Importante: SUBSTITUA os valores de custo abaixo (tabela DATA.custos) pelos valores reais do seu jogo.
A estrutura já está pronta para você só trocar os números.
]]
]]


local p = {}


-- =======================
    local html = mw.html.create()
-- CONFIGURAÇÃO DE DADOS
 
-- =======================
    html:wikitext(css)
-- Nome dos tiers em ordem de progressão.
-- Use chaves em minúsculas, sem acento, para evitar problemas.
local DATA = {
  tiers = { "bronze", "prata", "gold", "diamante" },


  -- Custo para subir 1 estrela DENTRO do mesmo tier.
    local box = html:tag("div")
  -- Para cada tier (chave), defina uma lista de 5 valores que representam o custo para ir:
    :addClass("boss-container")
  --  0 ➜ 1, 1 ➜ 2, 2 ➜ 3, 3 ➜ 4, 4 ➜ 5 estrelas.
     :css{
  -- Exemplo abaixo usa NÚMEROS DE PLACEHOLDER! Troque pelos números reais.
        background = "#18181b",
  custos = {
         ["border-radius"] = "12px",
     bronze = {
        padding = "30px",
      estrelas = {
         color = "#fff",
         { berry = 100, frag = 2 }, -- 0->1
         width = "100%",
         { berry = 150, frag = 3 },  -- 1->2
         margin = "auto",
         { berry = 200, frag = 4 },  -- 2->3
         ["font-family"] = "Verdana,sans-serif",
         { berry = 250, frag = 5 }, -- 3->4
        ["box-sizing"] = "border-box"
         { berry = 300, frag = 6 },  -- 4->5
     }
      },
      -- Custo para PROMOVER do tier atual para o próximo (depois de 5★).
      promover = { berry = 500, frag = 10 },
     },


     prata = {
     ----------------------------------------------------
      estrelas = {
    -- Cabeçalho
        { berry = 400, frag = 4 },
    ----------------------------------------------------
        { berry = 500, frag = 5 },
    box:tag("div")
         { berry = 600, frag = 6 },
         :css{ ["font-size"] = "1.5em", ["font-weight"] = "bold", ["margin-bottom"] = "10px" }
        { berry = 700, frag = 7 },
         :wikitext("Bosses")
         { berry = 800, frag = 8 },
      },
      promover = { berry = 1200, frag = 16 },
    },


     gold = {
     local var = box:tag("div")
      estrelas = {
         :css("margin-bottom", "24px")
        { berry = 900,  frag = 9 },
        { berry = 1100, frag = 10 },
        { berry = 1300, frag = 11 },
         { berry = 1500, frag = 12 },
        { berry = 1700, frag = 13 },
      },
      promover = { berry = 2500, frag = 24 },
    },


     diamante = {
     var:tag("span")
      estrelas = {
        :css{
        { berry = 2000, frag = 15 },
            ["background-color"] = "#232329",
        { berry = 2300, frag = 16 },
            ["border-radius"] = "7px 0 0 7px",
        { berry = 2600, frag = 17 },
            padding = "7px 20px",
        { berry = 2900, frag = 18 },
            ["font-size"] = "1em",
        { berry = 3200, frag = 19 },
            color = "#cbcdd7",
      },
            ["font-weight"] = "600"
      -- Se diamante for o último tier, manter promover = nil ou {}.
        }
      promover = nil,
        :wikitext("Mecanica Elite")
    },
  },
}


-- =======================
    var:tag("span")
-- FUNÇÕES AUXILIARES
        :css{
-- =======================
            ["background-color"] = "#19171c",
            ["border-radius"] = "0 7px 7px 0",
            padding = "7px 20px",
            ["font-size"] = "1em",
            color = "#fff",
            ["font-weight"] = "600",
            border = "2px solid #c7a047",
            ["border-left"] = "0"
        }
        :wikitext("Mecanica Hard")


local function norm(s)
    ----------------------------------------------------
  if type(s) ~= "string" then return s end
    -- Corpo principal (responsivo)
  s = s:lower()
    ----------------------------------------------------
  s = s:gsub("[áàâã]","a"):gsub("[éê]","e"):gsub("[í]","i"):gsub("[óôõ]","o"):gsub("[ú]","u"):gsub("ç","c")
    local main = box:tag("div")
  return s
        :addClass("boss-main")
end
        :css{
            display = "flex",
            gap = "20px",
            ["align-items"] = "center",
            ["justify-content"] = "space-between",
            ["flex-wrap"] = "wrap"
        }


local function findTierIndex(tier)
    main:tag("div")
  local t = norm(tier)
        :addClass("boss-img-box")
  for i, name in ipairs(DATA.tiers) do
        :css{ ["flex"] = "none" }
    if norm(name) == t then return i end
        :wikitext(string.format("[[Arquivo:%s|90px]]", img))
  end
  return nil
end


local function validateInputs(args)
    local textBox = main:tag("div")
  local deTier = args.deTier or args.de or args.fromTier
        :css{ ["flex"] = "1", ["min-width"] = "200px" }
  local paraTier = args.paraTier or args.para or args.toTier
  local deEstrelas = tonumber(args.deEstrelas or args.estrelas or args.fromStars) or 0
  local paraEstrelas = tonumber(args.paraEstrelas or args.toStars) or 0


  if not deTier or not paraTier then
    textBox:tag("div")
    return nil, "Informe os parâmetros deTier e paraTier."
        :css{ ["font-size"] = "1.2em", ["font-weight"] = "bold", color = "#e82b2b" }
  end
        :wikitext(nome)


  local deIdx = findTierIndex(deTier)
    textBox:tag("div")
  local paraIdx = findTierIndex(paraTier)
        :css{ ["font-size"] = "95%", color = "#eaa85d", ["font-style"] = "italic" }
  if not deIdx then return nil, "Tier inicial inválido: " .. tostring(deTier) end
        :wikitext(string.format('"%s"', frase))
  if not paraIdx then return nil, "Tier de destino inválido: " .. tostring(paraTier) end


  if deEstrelas < 0 or deEstrelas > 5 then
    ----------------------------------------------------
     return nil, "deEstrelas deve estar entre 0 e 5."
    -- Stats
  end
    ----------------------------------------------------
  if paraEstrelas < 0 or paraEstrelas > 5 then
     local stats = main:tag("div")
    return nil, "paraEstrelas deve estar entre 0 e 5."
        :addClass("boss-stats")
  end
        :css{
            display = "flex",
            ["flex-direction"] = "column",
            ["align-items"] = "flex-end",
            gap = "6px",
            ["min-width"] = "160px"
        }


  -- Também não permitir alvo "antes" da origem.
    local statBox = stats:tag("div")
  if paraIdx < deIdx or (paraIdx == deIdx and paraEstrelas < deEstrelas) then
        :css{
    return nil, "O destino deve ser maior que a origem."
            ["background-color"] = "#222126",
  end
            ["border-radius"] = "8px",
            padding = "12px 20px",
            ["min-width"] = "170px"
        }


  return {
     local sline = statBox:tag("div")
     deIdx = deIdx,
        :css{
    paraIdx = paraIdx,
            display = "flex",
    deTier = DATA.tiers[deIdx],
            ["align-items"] = "center",
    paraTier = DATA.tiers[paraIdx],
            ["justify-content"] = "center",
    deEstrelas = deEstrelas,
            gap = "16px",
    paraEstrelas = paraEstrelas,
            ["flex-wrap"] = "wrap"
    moeda = args.moeda or "berry",
        }
    frag = args.frag or "fragmentos",
    mostrarPassos = norm(tostring(args.mostrarPassos or "nao")) == "sim",
  }
end


-- Soma custos de estrelas dentro de um tier, do nível deEstrelas até (exclusivo) alvoEstrelas.
    sline:wikitext(string.format('<span style="color:#fb3d3d;font-weight:bold;font-size:1.15em;">&#x2764;&#xFE0F; %s</span>', hp))
local function somarEstrelas(tierKey, deEstrelas, alvoEstrelas)
     sline:wikitext(string.format('<span style="color:#ffe568;font-weight:bold;font-size:1.08em;">&#x1F4B0; %s</span>', exp))
  local cust = DATA.custos[tierKey]
    sline:wikitext(string.format('<span style="color:#6ca8fb;font-weight:bold;font-size:1.04em;">&#x2694;&#xFE0F; %s</span>', nivel))
  local total = { berry = 0, frag = 0 }
  local passos = {}
  if not cust or not cust.estrelas then return total, passos end
  for s = deEstrelas, alvoEstrelas - 1 do
     local step = cust.estrelas[s + 1] -- +1 porque tabela começa no 1
    if step then
      total.berry = total.berry + (step.berry or 0)
      total.frag  = total.frag  + (step.frag or 0)
      table.insert(passos, { tipo = "estrela", from = s, to = s + 1, tier = tierKey, berry = step.berry or 0, frag = step.frag or 0 })
    end
  end
  return total, passos
end


-- =======================
    stats:tag("div")
-- LÓGICA PRINCIPAL
        :css{
-- =======================
            ["margin-top"] = "5px",
            ["font-size"] = "90%",
            color = "#cfccff",
            ["text-align"] = "right"
        }
        :wikitext(string.format(
            "<b>Necessario:</b> %s &nbsp;&nbsp; ",
            necessario, forte, reflete
        ))


local function calcular(args)
    ----------------------------------------------------
  local ok, errOrCfg = pcall(validateInputs, args)
  if not ok then return nil, errOrCfg end
  if not errOrCfg then return nil, "Parâmetros inválidos." end
  if type(errOrCfg) == "string" then return nil, errOrCfg end
  local cfg = errOrCfg


  local total = { berry = 0, frag = 0 }
    -- Espaço livre para conteúdo customizável do editor
  local passos = {}


  for idx = cfg.deIdx, cfg.paraIdx do
     ----------------------------------------------------
     local tierKey = DATA.tiers[idx]


    -- Definir início e fim das estrelas para este tier
     local conteudo = box:tag("div")
     local startStar = (idx == cfg.deIdx) and cfg.deEstrelas or 0
    local endStar  = (idx == cfg.paraIdx) and cfg.paraEstrelas or 5


    -- Somar estrelas do tier atual
        :addClass("boss-custom-content")
    local parc, pss = somarEstrelas(tierKey, startStar, endStar)
    total.berry = total.berry + parc.berry
    total.frag  = total.frag  + parc.frag
    for _, x in ipairs(pss) do table.insert(passos, x) end


    -- Se não for o último tier de destino e atingiu 5 estrelas, pagar promoção
        :css{
    if endStar == 5 and idx < cfg.paraIdx then
      local promo = (DATA.custos[tierKey] and DATA.custos[tierKey].promover) or { berry = 0, frag = 0 }
      total.berry = total.berry + (promo.berry or 0)
      total.frag  = total.frag  + (promo.frag or 0)
      table.insert(passos, { tipo = "promocao", tier = tierKey, para = DATA.tiers[idx + 1], berry = promo.berry or 0, frag = promo.frag or 0 })
    end
  end


  return { total = total, passos = passos, cfg = cfg }
            ["margin-top"] = "28px",
end


-- =======================
            background = "#232329",
-- RENDERIZAÇÃO (HTML simples / Wikitext)
-- =======================


local function formatNumero(n)
            ["border-radius"] = "10px",
  -- separador de milhar simples
  local s = tostring(math.floor(n or 0))
  local k
  while true do
    s, k = s:gsub("^(%d+)(%d%d%d)", "%1.%2")
    if k == 0 then break end
  end
  return s
end


local function renderResultado(res)
            padding = "18px",
  local moeda = res.cfg.moeda
  local fragN = res.cfg.frag


  local linhas = {}
            ["min-height"] = "40px"
  table.insert(linhas, "{| class=\"wikitable\" style=\"width:420px\"\n! colspan=2 | Totais\n|-")
  table.insert(linhas, string.format("| %s || %s\n|-", moeda, formatNumero(res.total.berry)))
  table.insert(linhas, string.format("| %s || %s\n|}", fragN, formatNumero(res.total.frag)))


  if res.cfg.mostrarPassos and #res.passos > 0 then
         }
    table.insert(linhas, "\n\n{| class=\"wikitable\" style=\"width:100%%\"\n! Passo !! Detalhe !! " .. moeda .. " !! " .. fragN .. "\n|-")
    for _, pss in ipairs(res.passos) do
      if pss.tipo == "estrela" then
         table.insert(linhas, string.format("| Estrela || %s: %d★ ➜ %d★ || %s || %s\n|-",
          pss.tier, pss.from, pss.to, formatNumero(pss.berry), formatNumero(pss.frag)))
      else
        table.insert(linhas, string.format("| Promoção || %s ➜ %s || %s || %s\n|-",
          pss.tier, pss.para, formatNumero(pss.berry), formatNumero(pss.frag)))
      end
    end
    table.insert(linhas, "|}")
  end


  return table.concat(linhas, "\n")
        :wikitext(g("conteudo", ""))  -- permite o uso de |conteudo= na predefinição
end


-- =======================
-- ENTRADA PÚBLICA (Scribunto)
-- =======================


function p.calc(frame)
  local args = frame.args
  -- permitir também Template: wrapper com parent
  if frame:getParent() then
    for k, v in pairs(frame:getParent().args) do
      if v ~= '' and args[k] == nil then args[k] = v end
    end
  end


  local res, err = calcular(args)
  if not res then
    return string.format("'''Erro:''' %s", err)
  end
  return renderResultado(res)
end


-- =======================
    return tostring(html)end
-- UTIL: DEPURAÇÃO VIA CONSOLE (opcional)
-- =======================
-- Você pode rodar no console do Scribunto para testar:
-- =p._test{deTier="bronze", deEstrelas=2, paraTier="diamante", paraEstrelas=4, mostrarPassos="sim"}
function p._test(args)
  local res, err = calcular(args)
  if not res then return "Erro: " .. err end
  return renderResultado(res)
end


return p
return p

Edição atual tal como às 18h27min de 5 de dezembro de 2025

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

-- Módulo:BossDisplay (responsivo)

local p = {}

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

    local function g(k, default)
        return mw.text.trim(args[k] or "") ~= "" and args[k] or default
    end

    local img        = g("img",        "Placeholder.png")
    local nome       = g("nome",       "Nome do Boss")
    local frase      = g("frase",      "Frase ou lema do boss.")
    local hp         = g("hp",         "???")
    local exp        = g("exp",        "???")
    local nivel      = g("nivel",      "???")
    local necessario = g("necessario",     "-")
    local comum      = g("comum",      "")
    local semiraro   = g("semiraro",   "")
    local raro       = g("raro",       "")
    local muitoRaro  = g("muitoraro",  "")

    ----------------------------------------------------
    -- CSS responsivo embutido
    ----------------------------------------------------
    local css = [[

]]


    local html = mw.html.create()

    html:wikitext(css)

    local box = html:tag("div")
    :addClass("boss-container")
    :css{
        background = "#18181b",
        ["border-radius"] = "12px",
        padding = "30px",
        color = "#fff",
        width = "100%",
        margin = "auto",
        ["font-family"] = "Verdana,sans-serif",
        ["box-sizing"] = "border-box"
    }

    ----------------------------------------------------
    -- Cabeçalho
    ----------------------------------------------------
    box:tag("div")
        :css{ ["font-size"] = "1.5em", ["font-weight"] = "bold", ["margin-bottom"] = "10px" }
        :wikitext("Bosses")

    local var = box:tag("div")
        :css("margin-bottom", "24px")

    var:tag("span")
        :css{
            ["background-color"] = "#232329",
            ["border-radius"] = "7px 0 0 7px",
            padding = "7px 20px",
            ["font-size"] = "1em",
            color = "#cbcdd7",
            ["font-weight"] = "600"
        }
        :wikitext("Mecanica Elite")

    var:tag("span")
        :css{
            ["background-color"] = "#19171c",
            ["border-radius"] = "0 7px 7px 0",
            padding = "7px 20px",
            ["font-size"] = "1em",
            color = "#fff",
            ["font-weight"] = "600",
            border = "2px solid #c7a047",
            ["border-left"] = "0"
        }
        :wikitext("Mecanica Hard")

    ----------------------------------------------------
    -- Corpo principal (responsivo)
    ----------------------------------------------------
    local main = box:tag("div")
        :addClass("boss-main")
        :css{
            display = "flex",
            gap = "20px",
            ["align-items"] = "center",
            ["justify-content"] = "space-between",
            ["flex-wrap"] = "wrap"
        }

    main:tag("div")
        :addClass("boss-img-box")
        :css{ ["flex"] = "none" }
        :wikitext(string.format("[[Arquivo:%s|90px]]", img))

    local textBox = main:tag("div")
        :css{ ["flex"] = "1", ["min-width"] = "200px" }

    textBox:tag("div")
        :css{ ["font-size"] = "1.2em", ["font-weight"] = "bold", color = "#e82b2b" }
        :wikitext(nome)

    textBox:tag("div")
        :css{ ["font-size"] = "95%", color = "#eaa85d", ["font-style"] = "italic" }
        :wikitext(string.format('"%s"', frase))

    ----------------------------------------------------
    -- Stats
    ----------------------------------------------------
    local stats = main:tag("div")
        :addClass("boss-stats")
        :css{
            display = "flex",
            ["flex-direction"] = "column",
            ["align-items"] = "flex-end",
            gap = "6px",
            ["min-width"] = "160px"
        }

    local statBox = stats:tag("div")
        :css{
            ["background-color"] = "#222126",
            ["border-radius"] = "8px",
            padding = "12px 20px",
            ["min-width"] = "170px"
        }

    local sline = statBox:tag("div")
        :css{
            display = "flex",
            ["align-items"] = "center",
            ["justify-content"] = "center",
            gap = "16px",
            ["flex-wrap"] = "wrap"
        }

    sline:wikitext(string.format('<span style="color:#fb3d3d;font-weight:bold;font-size:1.15em;">&#x2764;&#xFE0F; %s</span>', hp))
    sline:wikitext(string.format('<span style="color:#ffe568;font-weight:bold;font-size:1.08em;">&#x1F4B0; %s</span>', exp))
    sline:wikitext(string.format('<span style="color:#6ca8fb;font-weight:bold;font-size:1.04em;">&#x2694;&#xFE0F; %s</span>', nivel))

    stats:tag("div")
        :css{
            ["margin-top"] = "5px",
            ["font-size"] = "90%",
            color = "#cfccff",
            ["text-align"] = "right"
        }
        :wikitext(string.format(
            "<b>Necessario:</b> %s &nbsp;&nbsp; ",
            necessario, forte, reflete
        ))

    ----------------------------------------------------

    -- Espaço livre para conteúdo customizável do editor

    ----------------------------------------------------

    local conteudo = box:tag("div")

        :addClass("boss-custom-content")

        :css{

            ["margin-top"] = "28px",

            background = "#232329",

            ["border-radius"] = "10px",

            padding = "18px",

            ["min-height"] = "40px"

        }

        :wikitext(g("conteudo", ""))  -- permite o uso de |conteudo= na predefinição




    return tostring(html)end

return p