Module:StatsPage

From Fire Emblem Heroes Wiki
Jump to: navigation, search
Documentation for this module may be created at Module:StatsPage/doc
local util = require('Module:Util')
local getArgs = require('Module:Arguments').getArgs
local ListUtil = require 'Module:ListUtil'
local FEHStatUtil = require 'Module:FEHStatUtil'

local SUM_CSS_PROP = 'font-style'
local SUM_CSS_VAL = 'italic'

local makeStatTableHeader = function ()
  return mw.html.create('table')
    :addClass('wikitable default'):css('text-align', 'center'):css('width', '500px')
    :tag('tr')
      :tag('th'):css('width', '14%'):wikitext('Rarity'):done()
      :tag('th'):css('width', '14%'):wikitext('HP'):done()
      :tag('th'):css('width', '14%'):wikitext('Atk'):done()
      :tag('th'):css('width', '14%'):wikitext('Spd'):done()
      :tag('th'):css('width', '14%'):wikitext('Def'):done()
      :tag('th'):css('width', '14%'):wikitext('Res'):done()
      :tag('th'):css('width', '14%'):css(SUM_CSS_PROP, SUM_CSS_VAL):wikitext('Total'):done()
      :done()
    :done()
end

local getStatTotalBounds = function (neut, bane, boon)
  local sums = {
    neut[1] + neut[2] + neut[3] + neut[4] + neut[5],
    boon[1] + bane[2] + neut[3] + neut[4] + neut[5],
    boon[1] + neut[2] + bane[3] + neut[4] + neut[5],
    boon[1] + neut[2] + neut[3] + bane[4] + neut[5],
    boon[1] + neut[2] + neut[3] + neut[4] + bane[5],
    bane[1] + boon[2] + neut[3] + neut[4] + neut[5],
    neut[1] + boon[2] + bane[3] + neut[4] + neut[5],
    neut[1] + boon[2] + neut[3] + bane[4] + neut[5],
    neut[1] + boon[2] + neut[3] + neut[4] + bane[5],
    bane[1] + neut[2] + boon[3] + neut[4] + neut[5],
    neut[1] + bane[2] + boon[3] + neut[4] + neut[5],
    neut[1] + neut[2] + boon[3] + bane[4] + neut[5],
    neut[1] + neut[2] + boon[3] + neut[4] + bane[5],
    bane[1] + neut[2] + neut[3] + boon[4] + neut[5],
    neut[1] + bane[2] + neut[3] + boon[4] + neut[5],
    neut[1] + neut[2] + bane[3] + boon[4] + neut[5],
    neut[1] + neut[2] + neut[3] + boon[4] + bane[5],
    bane[1] + neut[2] + neut[3] + neut[4] + boon[5],
    neut[1] + bane[2] + neut[3] + neut[4] + boon[5],
    neut[1] + neut[2] + bane[3] + neut[4] + boon[5],
    neut[1] + neut[2] + neut[3] + bane[4] + boon[5],
  }
  return math.min(unpack(sums)), math.max(unpack(sums))
end

local p = {}

function p._statsPage(frame, args, isEnemy)
  local RARITY_TXT = util.getRarityTexts()

  -- parsing inputs
  --Hero
  args.Hero = args.Hero or mw.title.getCurrentTitle().text

  --Lv1 stats
  local level1Inputs = ListUtil.map({
    args.Lv1HP or '', args.Lv1ATK or '', args.Lv1SPD or '', args.Lv1DEF or '', args.Lv1RES or '',
  }, function (x) return tonumber(x) or false end)
  if ListUtil.find(level1Inputs, false) then
    return makeStatTableHeader()
  end

  --Set up tables for all Lv1 stats
  local full1Neuts = FEHStatUtil.fullLv1Stats(level1Inputs)
  local full1Banes = ListUtil.map(full1Neuts, function (t) return ListUtil.map(t, function (base) return base - 1 end) end)
  local full1Boons = ListUtil.map(full1Neuts, function (t) return ListUtil.map(t, function (base) return base + 1 end) end)

  --Growth rates
  local rateNeuts = ListUtil.map({
    args.GRHP or '', args.GRATK or '', args.GRSPD or '', args.GRDEF or '', args.GRRES or '',
  }, function (x) return tonumber(x) or false end)
  if ListUtil.find(rateNeuts, false) then
    return makeStatTableHeader()
  end

  local full40Neuts = FEHStatUtil.fullLv40Stats(rateNeuts, full1Neuts)
  local full40Banes = FEHStatUtil.fullLv40Stats(ListUtil.map(rateNeuts, function (rate) return rate - 5 end), full1Banes)
  local full40Boons = FEHStatUtil.fullLv40Stats(ListUtil.map(rateNeuts, function (rate) return rate + 5 end), full1Boons)

  --Fill in rows of Lv1 table
  local Lv1StatTable = makeStatTableHeader()
  for rarity, statset in ipairs(full1Neuts) do
    local tr = Lv1StatTable:tag('tr')
    tr:tag('td'):wikitext(RARITY_TXT[rarity])
    for stat, val in ipairs(statset) do
      local statString = isEnemy and tostring(val) or ('%s/%s/%s'):format(full1Banes[rarity][stat], val, full1Boons[rarity][stat])
      tr:tag('td'):wikitext(statString)
    end
    tr:tag('td'):wikitext(ListUtil.sum(statset)):css(SUM_CSS_PROP, SUM_CSS_VAL)
  end

  --Fill in rows of Lv40 table
  local Lv40StatTable = makeStatTableHeader()
  for rarity, neutset in ipairs(full40Neuts) do
    local baneset = full40Banes[rarity]
    local boonset = full40Boons[rarity]
    local tr = Lv40StatTable:tag('tr')
    tr:tag('td'):wikitext(RARITY_TXT[rarity])

    for stat, val in ipairs(neutset) do
      local statString = isEnemy and tostring(val) or ('%s/%s/%s'):format(baneset[stat], val, boonset[stat])
      tr:tag('td'):wikitext(statString)
    end
  
    local sumString = '-'
    local sum = ListUtil.sum(neutset)
    if not isEnemy then
      local lo, hi = getStatTotalBounds(neutset, baneset, boonset)
      sumString = lo ~= hi and ('%s~%s'):format(lo, hi) or tostring(lo)
    else
      sumString = tostring(sum)
    end
    tr:tag('td'):wikitext(sumString):css(SUM_CSS_PROP, SUM_CSS_VAL)
  end

  --Fill in rows of GR table
  local wikiGRTable = makeStatTableHeader()
  local tr = wikiGRTable:tag('tr')
  tr:tag('td'):wikitext(RARITY_TXT[3])
  for _, rate in ipairs(rateNeuts) do
    tr:tag('td'):wikitext(rate .. '%')
  end
  tr:tag('td')
    :wikitext(ListUtil.sum(rateNeuts) .. '%')
    :css(SUM_CSS_PROP, SUM_CSS_VAL)

  if isEnemy then
    return '<h3>Level 1 Stats</h3>' ..
      tostring(Lv1StatTable) .. '<h3>Level 40 Stats</h3>' .. tostring(Lv40StatTable) ..
      '<h3>Growth Rates</h3><i>This set of values, after being multiplied by a rarity factor, determines how much each stat will increase from level 1 to level 40, see [[Stat growth#Growth values|stat growth]].</i>' .. tostring(wikiGRTable)
  else
    return 'All stats have a degree of variation. The [[stat growth]] page explains how the variation works.<h3>Level 1 stats</h3>' ..
      tostring(Lv1StatTable) .. '<h3>Level 40 stats</h3>' .. tostring(Lv40StatTable) ..
      '<h3>Growth Rates</h3><i>This set of values, after being multiplied by a rarity factor, determines how much each stat will increase from level 1 to level 40, see [[Stat growth#Growth values|stat growth]].</i>' .. tostring(wikiGRTable) ..
      '<h3>Stats between level 1 and 40</h3>For stat values between level 1 and 40, see [[/Level 1-40 stats|this page]].'
  end
end

function p.statsPage(frame)
  args = getArgs(frame, {wrappers = "Template:Stats Page"})
  return p._statsPage(frame, args, false)
end

function p.enemyStatsPage(frame)
  args = getArgs(frame, {wrappers = 'Template:Stats Page/Enemy'})
  return p._statsPage(frame, args, true)
end

return p