Tests
All tests passed.
Name | Expected | Actual | |
---|---|---|---|
testFastSupportLevels | |||
testFastWarriorLevels | |||
testNormalSupportLevels | |||
testNormalWarriorLevels |
local getArgs = require("Module:Arguments").getArgs
local yesno = require("Module:Yesno")
local p = {}
local black = '★'
local white = '☆'
local multis = {1.0, 1.1, 1.2, 1.3, 1.4, 1.7, 2.0, 2.3, 2.6, 3.0}
local function round(n)
return math.floor(n + 0.5)
end
local function count_stars(s)
local total = tonumber(s)
local _, b_count, w_coun
if s == nil then return 0 end
if total == nil then
_, b_count = string.gsub(s, black, '')
_, w_count = string.gsub(s, white, '')
total = b_count + w_count * 10
end
return total
end
local function number_to_stars(n)
local total = tonumber(n)
local w_count = math.floor(total / 10)
local b_count = total % 10
return string.rep(white, w_count) .. string.rep(black, b_count)
end
local function jobtype_icon(s)
local s = mw.ustring.lower(s or '')
if (s == 'warrior' or
s == 'mage' or
s == 'ranger' or
s == 'monk') then
return string.format('[[File:%s_Icon.png|20x20px|link=]]', s)
end
end
function p.ultimate(frame)
local args = getArgs(frame,{
wrappers = "Template:Ultimate ability stat"
})
return p._ultimate(args)
end
function p._ultimate(args)
local gauge = {160, 155, 150, 140, 135, 130, 125, 110, 100, 80}
local name = args.name
local jobtype = args.jobtype or args.type
local info = args.info or args.description
local atk = args.atk or args.attack
atk = tonumber(string.match(atk or '', '(%d+)%%?')) or 0
local brk = args.brk or args.breakpower
brk = tonumber(string.match(brk or '', '(%d+)%%?')) or 0
local const_atk = yesno(args.const_attack, false)
local const_brk = yesno(args.const_breakpower, false)
local critchance = args.critchance
local extra = args.extra
local total = count_stars(critchance)
local critstars = number_to_stars(total)
local tbl = {
{"Lv", "Ultimate Gauge", "Attack", "Break Power", "Crit Chance"}
}
for lv=1,10 do
local m = multis[lv]
local atk_n = atk * m
local brk_n = brk * m
if const_atk then atk_n = atk end
if const_brk then brk_n = brk end
local row = {
lv,
gauge[lv],
atk_n .. "%",
brk_n .. "%",
string.format("%s (%d%%)", critstars, total * 5)
}
tbl[#tbl+1] = row
end
local root = mw.html.create('')
root
:wikitext(jobtype_icon(jobtype))
:tag('b')
:wikitext(name)
:done()
:newline()
:tag("div")
:cssText("font-style:italic")
:wikitext('"' .. (info or '???') .. '"')
:done()
:newline()
local wikitable = root:tag('table')
:addClass('wikitable')
for i,row in ipairs(tbl) do
local tr = wikitable:tag('tr')
local tagname = (i == 1) and 'th' or 'td'
for j,col in ipairs(row) do
tr
:tag(tagname)
:wikitext(col)
:done()
end
tr:done():newline()
end
wikitable:done():newline()
if extra then
root:tag('b')
:wikitext('Added Effects: ')
root:wikitext(extra)
end
return tostring(root)
end
function p._main(args)
local args = args
local rarity = args.rarity
local atk = args.atk or args.attack
local brk = args.brk or args.breakpower
local crit = args.crit or args.critchance
local const_atk = yesno(args.const_attack, false)
local const_brk = yesno(args.const_breakpower, false)
local has_cooldown = yesno(args.has_cooldown, false)
if rarity == nil then
mw.log('ability stat: "rarity" argument is null or empty')
return ''
end
local cooldowns = {8, 7, 6, 5, 4, 3, 2, 2, 1, 1}
local fast = false
local rarities = {}
for a,b in string.gmatch(rarity, '(-?%d+)(%+?)') do
a = tonumber(a)
if a < 1 or 5 < a then
error("Rarity outside the range of 1~5: "..a..b)
elseif b == '+' then
fast = true
end
rarities[a] = true
end
atk = tonumber(atk) or 0
brk = tonumber(brk) or 0
local total = count_stars(crit)
local critstars = number_to_stars(total)
local crit_n = string.format("%s (%d%%)", critstars, total*5)
-- If attack is 0, then it's a support ability.
-- If break is 0, then it's a support ability.
local support = atk == 0 or brk == 0
local show_atk = atk > 0
local show_brk = brk > 0
local show_cooldown = support or (fast and not crit) or has_cooldown
local show_crit = crit ~= nil and total >= 0
local columns = {}
local rows = {}
local level
local m, c -- y = mx + c
if support then
m = 1
c = 1
else
m = 2
c = 0
end
local levels = {}
if fast then
for rarity=1,5 do
local has_rarity = rarities[rarity]
if has_rarity then
levels[#levels+1] = rarity * m + c
end
end
else
local max_rarity = 0 -- largest rarity
for i=1,5 do
if rarities[i] and max_rarity < i then
max_rarity = i
end
end
for level=1, max_rarity * m + c do
levels[#levels+1] = level
end
end
table.insert(columns, 'ALv.')
if show_atk then table.insert(columns, 'Attack') end
if show_brk then table.insert(columns, 'Break Power') end
if show_crit then table.insert(columns, 'Crit Chance') end
if show_cooldown then table.insert(columns, 'Cooldown') end
for i,level in ipairs(levels) do
local row = {}
local m = multis[level]
row[#row+1] = level
if show_atk then
local atk_n = atk
if not const_atk then atk_n = round(atk * m) end
row[#row+1] = atk_n
end
if show_brk then
local brk_n = brk
if not const_brk then brk_n = round(brk * m) end
row[#row+1] = brk_n
end
if show_crit then
row[#row+1] = crit_n
end
if show_cooldown then
local cooldown = cooldowns[level]
row[#row+1] = cooldown
end
rows[#rows+1] = row
end
local wikitable, tr
wikitable = mw.html.create('table'):addClass('wikitable'):newline()
tr = mw.html.create('tr')
for i,th in ipairs(columns) do
tr:tag('th'):wikitext(th)
end
wikitable:node(tr):newline()
for i,row in ipairs(rows) do
tr = mw.html.create('tr')
for j,td in ipairs(row) do
tr:tag('td'):wikitext(td)
end
wikitable:node(tr):newline()
end
return tostring(wikitable)
end
function p.main(frame)
local args = getArgs(frame,{
wrappers = "Template:Ability stat"
})
return p._main(args)
end
function p._test()
local args = {
{rarity="4+",attack="450",breakpower="1",critchance="0",has_cooldown="n"},
}
for i,v in ipairs(args) do
mw.log(i, p._main(v))
end
end
return p