Mudanças entre as edições de "Módulo:Gb"
Ir para navegação
Ir para pesquisar
| Linha 1: | Linha 1: | ||
--[[ | |||
Module:CalculadoraTier | |||
Calculadora de recursos (berry e fragmentos) para evoluir um personagem por Tiers e Estrelas. | |||
✔ Como usar na wiki (Wikitext): | |||
{{#invoke:CalculadoraTier|calc | |||
|deTier=bronze | |||
|deEstrelas=2 | |||
|paraTier=diamante | |||
|paraEstrelas=4 | |||
}} | |||
Parâmetros opcionais: | |||
|moeda=berry -- nome exibido para a moeda (default: "berry") | |||
|frag=fragmentos -- nome exibido para os fragmentos (default: "fragmentos") | |||
|mostrarPassos=sim -- mostra o passo a passo (sim/não) | |||
📌 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 p = {} | ||
-- === | -- ======================= | ||
-- CONFIGURAÇÃO DE DADOS | |||
-- ======================= | |||
-- 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. | |||
-- Para cada tier (chave), defina uma lista de 5 valores que representam o custo para ir: | |||
-- 0 ➜ 1, 1 ➜ 2, 2 ➜ 3, 3 ➜ 4, 4 ➜ 5 estrelas. | |||
-- Exemplo abaixo usa NÚMEROS DE PLACEHOLDER! Troque pelos números reais. | |||
custos = { | |||
bronze = { | |||
estrelas = { | |||
{ berry = 100, frag = 2 }, -- 0->1 | |||
{ berry = 150, frag = 3 }, -- 1->2 | |||
{ berry = 200, frag = 4 }, -- 2->3 | |||
{ berry = 250, frag = 5 }, -- 3->4 | |||
{ 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 = { | |||
{ berry = 400, frag = 4 }, | |||
{ berry = 500, frag = 5 }, | |||
{ berry = 600, frag = 6 }, | |||
{ berry = 700, frag = 7 }, | |||
{ berry = 800, frag = 8 }, | |||
}, | |||
promover = { berry = 1200, frag = 16 }, | |||
}, | |||
gold = { | |||
estrelas = { | |||
{ 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 = { | |||
estrelas = { | |||
{ berry = 2000, frag = 15 }, | |||
{ berry = 2300, frag = 16 }, | |||
{ berry = 2600, frag = 17 }, | |||
{ berry = 2900, frag = 18 }, | |||
{ berry = 3200, frag = 19 }, | |||
}, | |||
-- Se diamante for o último tier, manter promover = nil ou {}. | |||
promover = nil, | |||
}, | |||
}, | |||
} | |||
-- ======================= | |||
-- FUNÇÕES AUXILIARES | |||
-- ======================= | |||
local function norm(s) | |||
if type(s) ~= "string" then return s end | |||
s = s:lower() | |||
s = s:gsub("[áàâã]","a"):gsub("[éê]","e"):gsub("[í]","i"):gsub("[óôõ]","o"):gsub("[ú]","u"):gsub("ç","c") | |||
return s | |||
end | |||
local function findTierIndex(tier) | |||
return | local t = norm(tier) | ||
for i, name in ipairs(DATA.tiers) do | |||
if norm(name) == t then return i end | |||
end | |||
return nil | |||
end | end | ||
local function | local function validateInputs(args) | ||
local deTier = args.deTier or args.de or args.fromTier | |||
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 | |||
return nil, "Informe os parâmetros deTier e paraTier." | |||
end | |||
local deIdx = findTierIndex(deTier) | |||
local paraIdx = findTierIndex(paraTier) | |||
if not deIdx then return nil, "Tier inicial inválido: " .. tostring(deTier) end | |||
if not paraIdx then return nil, "Tier de destino inválido: " .. tostring(paraTier) end | |||
end | if deEstrelas < 0 or deEstrelas > 5 then | ||
return nil, "deEstrelas deve estar entre 0 e 5." | |||
end | |||
if paraEstrelas < 0 or paraEstrelas > 5 then | |||
return nil, "paraEstrelas deve estar entre 0 e 5." | |||
end | |||
-- Também não permitir alvo "antes" da origem. | |||
if paraIdx < deIdx or (paraIdx == deIdx and paraEstrelas < deEstrelas) then | |||
return nil, "O destino deve ser maior que a origem." | |||
end | |||
return { | |||
deIdx = deIdx, | |||
paraIdx = paraIdx, | |||
deTier = DATA.tiers[deIdx], | |||
paraTier = DATA.tiers[paraIdx], | |||
deEstrelas = deEstrelas, | |||
paraEstrelas = paraEstrelas, | |||
moeda = args.moeda or "berry", | |||
frag = args.frag or "fragmentos", | |||
mostrarPassos = norm(tostring(args.mostrarPassos or "nao")) == "sim", | |||
} | |||
end | end | ||
local function | -- Soma custos de estrelas dentro de um tier, do nível deEstrelas até (exclusivo) alvoEstrelas. | ||
local function somarEstrelas(tierKey, deEstrelas, alvoEstrelas) | |||
local cust = DATA.custos[tierKey] | |||
local total = { berry = 0, frag = 0 } | |||
local passos = {} | |||
local | if not cust or not cust.estrelas then return total, passos end | ||
if | 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 | ||
end | |||
return total, passos | |||
end | end | ||
local function | -- ======================= | ||
-- LÓGICA PRINCIPAL | |||
-- ======================= | |||
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 } | |||
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 startStar = (idx == cfg.deIdx) and cfg.deEstrelas or 0 | |||
local endStar = (idx == cfg.paraIdx) and cfg.paraEstrelas or 5 | |||
-- Somar estrelas do tier atual | |||
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 | |||
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 | ||
end | |||
return { total = total, passos = passos, cfg = cfg } | |||
end | end | ||
-- ======================= | |||
-- RENDERIZAÇÃO (HTML simples / Wikitext) | |||
-- ======================= | |||
local function formatNumero(n) | |||
-- 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 | end | ||
local function renderResultado(res) | |||
local moeda = res.cfg.moeda | |||
local fragN = res.cfg.frag | |||
local linhas = {} | |||
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") | |||
end | |||
if | -- ======================= | ||
-- 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 | ||
end | |||
local res, err = calcular(args) | |||
if not res then | |||
return string.format("'''Erro:''' %s", err) | |||
end | |||
return renderResultado(res) | |||
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 | end | ||
return p | return p | ||
Edição das 19h47min de 26 de setembro de 2025
A documentação para este módulo pode ser criada em Módulo:Gb/doc
--[[
Module:CalculadoraTier
Calculadora de recursos (berry e fragmentos) para evoluir um personagem por Tiers e Estrelas.
✔ Como usar na wiki (Wikitext):
{{#invoke:CalculadoraTier|calc
|deTier=bronze
|deEstrelas=2
|paraTier=diamante
|paraEstrelas=4
}}
Parâmetros opcionais:
|moeda=berry -- nome exibido para a moeda (default: "berry")
|frag=fragmentos -- nome exibido para os fragmentos (default: "fragmentos")
|mostrarPassos=sim -- mostra o passo a passo (sim/não)
📌 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 = {}
-- =======================
-- CONFIGURAÇÃO DE DADOS
-- =======================
-- 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.
-- Para cada tier (chave), defina uma lista de 5 valores que representam o custo para ir:
-- 0 ➜ 1, 1 ➜ 2, 2 ➜ 3, 3 ➜ 4, 4 ➜ 5 estrelas.
-- Exemplo abaixo usa NÚMEROS DE PLACEHOLDER! Troque pelos números reais.
custos = {
bronze = {
estrelas = {
{ berry = 100, frag = 2 }, -- 0->1
{ berry = 150, frag = 3 }, -- 1->2
{ berry = 200, frag = 4 }, -- 2->3
{ berry = 250, frag = 5 }, -- 3->4
{ 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 = {
{ berry = 400, frag = 4 },
{ berry = 500, frag = 5 },
{ berry = 600, frag = 6 },
{ berry = 700, frag = 7 },
{ berry = 800, frag = 8 },
},
promover = { berry = 1200, frag = 16 },
},
gold = {
estrelas = {
{ 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 = {
estrelas = {
{ berry = 2000, frag = 15 },
{ berry = 2300, frag = 16 },
{ berry = 2600, frag = 17 },
{ berry = 2900, frag = 18 },
{ berry = 3200, frag = 19 },
},
-- Se diamante for o último tier, manter promover = nil ou {}.
promover = nil,
},
},
}
-- =======================
-- FUNÇÕES AUXILIARES
-- =======================
local function norm(s)
if type(s) ~= "string" then return s end
s = s:lower()
s = s:gsub("[áàâã]","a"):gsub("[éê]","e"):gsub("[í]","i"):gsub("[óôõ]","o"):gsub("[ú]","u"):gsub("ç","c")
return s
end
local function findTierIndex(tier)
local t = norm(tier)
for i, name in ipairs(DATA.tiers) do
if norm(name) == t then return i end
end
return nil
end
local function validateInputs(args)
local deTier = args.deTier or args.de or args.fromTier
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
return nil, "Informe os parâmetros deTier e paraTier."
end
local deIdx = findTierIndex(deTier)
local paraIdx = findTierIndex(paraTier)
if not deIdx then return nil, "Tier inicial inválido: " .. tostring(deTier) end
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."
end
if paraEstrelas < 0 or paraEstrelas > 5 then
return nil, "paraEstrelas deve estar entre 0 e 5."
end
-- Também não permitir alvo "antes" da origem.
if paraIdx < deIdx or (paraIdx == deIdx and paraEstrelas < deEstrelas) then
return nil, "O destino deve ser maior que a origem."
end
return {
deIdx = deIdx,
paraIdx = paraIdx,
deTier = DATA.tiers[deIdx],
paraTier = DATA.tiers[paraIdx],
deEstrelas = deEstrelas,
paraEstrelas = paraEstrelas,
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.
local function somarEstrelas(tierKey, deEstrelas, alvoEstrelas)
local cust = DATA.custos[tierKey]
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
-- =======================
-- LÓGICA PRINCIPAL
-- =======================
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 }
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 startStar = (idx == cfg.deIdx) and cfg.deEstrelas or 0
local endStar = (idx == cfg.paraIdx) and cfg.paraEstrelas or 5
-- Somar estrelas do tier atual
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
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 }
end
-- =======================
-- RENDERIZAÇÃO (HTML simples / Wikitext)
-- =======================
local function formatNumero(n)
-- 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)
local moeda = res.cfg.moeda
local fragN = res.cfg.frag
local linhas = {}
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")
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
-- =======================
-- 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