Difference between revisions of "Module:Apt"

From CrawlWiki
Jump to: navigation, search
m (fixing draconian exceptions?)
m (Fix)
 
(23 intermediate revisions by 3 users not shown)
Line 19: Line 19:
 
end
 
end
  
local function species_sorted()
+
local function is_obsolete_sk(skill)
 +
  return skill == "Charms" or skill == "Slings" or skill == "Bows" or skill == "Crossbows" or skill == "Stabbing" or skill == "Traps"
 +
end
 +
 
 +
local function is_spell_sk(skill)
 +
  return skill == "Spellcasting" or skill == "Conjurations" or skill == "Hexes" or skill == "Summonings" or skill == "Necromancy" or skill == "Translocations" or skill == "Fire Magic" or skill == "Ice Magic" or skill == "Air Magic" or skill == "Earth Magic" or skill == "Alchemy"
 +
end
 +
 
 +
local function species_sorted(include_obsolete)
 +
  include_obsolete = include_obsolete or false
 
   local species = {}
 
   local species = {}
 
   for sp in pairs(data) do
 
   for sp in pairs(data) do
     if not (is_colored_draconian(sp) or is_obsolete(sp)) then
+
     if not is_colored_draconian(sp) and (include_obsolete or not is_obsolete(sp)) then
 
       table.insert(species, sp)
 
       table.insert(species, sp)
 
     end
 
     end
Line 28: Line 37:
 
   table.sort(species)
 
   table.sort(species)
 
   return species
 
   return species
 +
end
 +
 +
local function skill_average(skill)
 +
  local count = 0
 +
  local sum = 0
 +
  for name, sp in pairs(data) do
 +
    if sp.Aptitudes[skill] and not is_colored_draconian(name) and name ~= "Gnoll" and (is_obsolete_sk(skill) or not is_obsolete(name)) and (name ~= "Djinni" or not is_spell_sk(skill)) then
 +
      count = count + 1
 +
      sum = sum + sp.Aptitudes[skill]
 +
    end
 +
  end
 +
  return string.format("%.3f", sum / count)
 
end
 
end
 
   
 
   
Line 36: Line 57:
 
     return ""
 
     return ""
 
   end
 
   end
   return data[sp].Aptitudes[sk] or "N/A"
+
   if sp == "Average" then
 +
    return skill_average(sk)
 +
  else
 +
    return data[sp].Aptitudes[sk] or "N/A"
 +
  end
 
end
 
end
  
 
function p.skill_table(frame)
 
function p.skill_table(frame)
 +
  local browser_width = frame.args[2]
 +
  browser_width = tonumber(browser_width) or 50
 
   local skill = name_arg(frame)
 
   local skill = name_arg(frame)
 
   local headers = {}
 
   local headers = {}
   local species = species_sorted()
+
   local species = species_sorted(is_obsolete_sk(skill))
   for _, sp in ipairs(species) do
+
 
 +
  local sp_headers_1 = {}
 +
  local sp_headers_2 = {}
 +
   for i, sp in ipairs(species) do
 
     local header = ("'''[[%s|%s]]'''"):format(sp, data[sp].Abbrev)
 
     local header = ("'''[[%s|%s]]'''"):format(sp, data[sp].Abbrev)
     table.insert(headers, header)
+
     if i<browser_width then
 +
      table.insert(sp_headers_1, header)
 +
    else
 +
      table.insert(sp_headers_2, header)
 +
    end
 +
  end
 +
 
 +
  local sk_headers_1 = {}
 +
  local sk_headers_2 = {}
 +
  for i, sp in ipairs(species) do
 +
    local header = ("%s"):format(data[sp].Aptitudes[skill] or "N/A")
 +
    if i<browser_width then
 +
      table.insert(sk_headers_1, header)
 +
    else
 +
      table.insert(sk_headers_2, header)
 +
    end
 
   end
 
   end
 +
 
   local result = [[{| class="wikitable" border="1"
 
   local result = [[{| class="wikitable" border="1"
 
|-
 
|-
 
|]]
 
|]]
   result = result .. table.concat(headers, "\n|")
+
   result = result .. table.concat(sp_headers_1, "\n|")
   result = result .. "\n|-\n"
+
   result = result .. "\n|-\n| "
   for _, sp in ipairs(species) do
+
   result = result .. table.concat(sk_headers_1, "\n| ")
     result = result .. "| " .. (data[sp].Aptitudes[skill] or "N/A") .. "\n"
+
  if next(sp_headers_2) then
 +
     result = result .. "\n|-\n|"
 +
    result = result .. table.concat(sp_headers_2, "\n|")
 +
    result = result .. "\n|-\n| "
 +
    result = result .. table.concat(sk_headers_2, "\n| ")
 
   end
 
   end
   result = result .. "|}"
+
   result = result .. "\n|}"
 
   return result
 
   return result
 
end
 
end
Line 64: Line 114:
 
   local result = ''
 
   local result = ''
 
   for name, species in pairs(data) do
 
   for name, species in pairs(data) do
     if is_colored_draconian(name) and (not is_obsolete(name)) and species.Aptitudes[skill] ~= normal then
+
     if is_colored_draconian(name) and (is_obsolete_sk(skill) or not is_obsolete(name)) and species.Aptitudes[skill] ~= normal then
 
       local col = name:match("^%a*")
 
       local col = name:match("^%a*")
 
       result = result .. '* [[Draconian#' .. col .. '|' .. col .. ' draconian]]s get ' .. species.Aptitudes[skill] .. '.\n'
 
       result = result .. '* [[Draconian#' .. col .. '|' .. col .. ' draconian]]s get ' .. species.Aptitudes[skill] .. '.\n'
Line 70: Line 120:
 
   end
 
   end
 
   return result
 
   return result
end
 
 
function p.skill_average(frame)
 
  local skill = name_arg(frame)
 
  local count = 0
 
  local sum = 0
 
  for name, sp in pairs(data) do
 
    if sp.Aptitudes[skill] and not is_colored_draconian(name) then
 
      count = count + 1
 
      sum = sum + sp.Aptitudes[skill]
 
    end
 
  end
 
  return string.format("%.3f", sum / count)
 
 
end
 
end
  
Line 118: Line 155:
  
 
function p.aptitude_chart_general(frame)
 
function p.aptitude_chart_general(frame)
   local skills = {'Armour', 'Dodging', 'Stealth',
+
   local skills = {'Armour', 'Dodging',
  'Shields', 'Invocations', 'Evocations', 'Hit Points', 'Magic Points', 'Experience'}
+
  'Shields', 'Stealth', 'Invocations', 'Evocations', 'Shapeshifting', 'Hit Points', 'Magic Points', 'Experience'}
 
   local header = [=[
 
   local header = [=[
 
{| class="wikitable sortable" style="font-size:75%" border=1
 
{| class="wikitable sortable" style="font-size:75%" border=1
Line 125: Line 162:
 
! scope="col" | [[Armour (skill)|Arm]]
 
! scope="col" | [[Armour (skill)|Arm]]
 
! scope="col" | [[Dodging|Ddg]]
 
! scope="col" | [[Dodging|Ddg]]
 +
! scope="col" | [[Shields (skill)|Shd]]
 
! scope="col" | [[Stealth|Sth]]
 
! scope="col" | [[Stealth|Sth]]
! scope="col" | [[Shields (skill)|Shd]]
 
 
! scope="col" | [[Invocations|Inv]]
 
! scope="col" | [[Invocations|Inv]]
 
! scope="col" | [[Evocations|Evo]]
 
! scope="col" | [[Evocations|Evo]]
 +
! scope="col" | [[Shapeshifting|Shp]]
 
! scope="col" | [[HP]]
 
! scope="col" | [[HP]]
 
! scope="col" | [[MP]]
 
! scope="col" | [[MP]]
Line 138: Line 176:
  
 
function p.aptitude_chart_combat(frame)
 
function p.aptitude_chart_combat(frame)
   local skills = {'Fighting', 'Short Blades', 'Long Blades', 'Maces & Flails',
+
   local skills = {'Fighting', 'Maces & Flails',
   'Axes', 'Polearms', 'Staves', 'Unarmed Combat', 'Throwing', 'Ranged Weapons'}
+
   'Axes', 'Polearms', 'Staves', 'Unarmed Combat', 'Throwing', 'Short Blades', 'Long Blades', 'Ranged Weapons'}
 
   local header = [=[
 
   local header = [=[
 
{| class="wikitable sortable" style="font-size:75%" border=1
 
{| class="wikitable sortable" style="font-size:75%" border=1
 
! scope="col" | [[Species]]
 
! scope="col" | [[Species]]
 
! scope="col" | [[Fighting|Fgt]]
 
! scope="col" | [[Fighting|Fgt]]
! scope="col" | [[Short Blades|SBl]]
 
! scope="col" | [[Long Blades|LBl]]
 
 
! scope="col" | [[Maces &amp; Flails|M&amp;F]]
 
! scope="col" | [[Maces &amp; Flails|M&amp;F]]
 
! scope="col" | [[Axes|Axs]]
 
! scope="col" | [[Axes|Axs]]
Line 152: Line 188:
 
! scope="col" | [[Unarmed Combat|UC]]
 
! scope="col" | [[Unarmed Combat|UC]]
 
! scope="col" | [[Throwing|Thr]]
 
! scope="col" | [[Throwing|Thr]]
 +
! scope="col" | [[Short Blades|SBl]]
 +
! scope="col" | [[Long Blades|LBl]]
 
! scope="col" | [[Ranged Weapons|RW]]
 
! scope="col" | [[Ranged Weapons|RW]]
 
|-
 
|-
Line 160: Line 198:
 
function p.aptitude_chart_magic(frame)
 
function p.aptitude_chart_magic(frame)
 
   local skills = {'Spellcasting', 'Conjurations', 'Hexes',
 
   local skills = {'Spellcasting', 'Conjurations', 'Hexes',
   'Summonings', 'Necromancy', 'Translocations', 'Transmutations',  
+
   'Summonings', 'Necromancy', 'Translocations', 'Alchemy',  
   'Fire Magic', 'Ice Magic', 'Air Magic', 'Earth Magic', 'Poison Magic'}
+
   'Fire Magic', 'Ice Magic', 'Air Magic', 'Earth Magic'}
 
   local header = [=[
 
   local header = [=[
 
{| class="wikitable sortable" style="font-size:75%" border=1
 
{| class="wikitable sortable" style="font-size:75%" border=1
Line 171: Line 209:
 
! scope="col" | [[Necromancy|Nec]]
 
! scope="col" | [[Necromancy|Nec]]
 
! scope="col" | [[Translocations|Trl]]
 
! scope="col" | [[Translocations|Trl]]
! scope="col" | [[Transmutations|Trm]]
+
! scope="col" | [[Alchemy|Alc]]
 
! scope="col" | [[Fire Magic|Fir]]
 
! scope="col" | [[Fire Magic|Fir]]
 
! scope="col" | [[Ice Magic|Ice]]
 
! scope="col" | [[Ice Magic|Ice]]
 
! scope="col" | [[Air Magic|Air]]
 
! scope="col" | [[Air Magic|Air]]
 
! scope="col" | [[Earth Magic|Ear]]
 
! scope="col" | [[Earth Magic|Ear]]
! scope="col" | [[Poison Magic|Poi]]
 
 
|-
 
|-
 
]=]
 
]=]

Latest revision as of 14:55, 21 February 2024

Documentation for this module may be created at Module:Apt/doc

local p = {}

local data = mw.loadData('Module:Table of species')

local function name_arg(frame)
  local name = frame.args[1]
  if not name or name == "" then
    name = mw.title.getCurrentTitle().text
  end
  return name
end

local function is_colored_draconian(species)
  return species:match(" Draconian$")
end

local function is_obsolete(species)
  return data[species].Obsolete or false
end

local function is_obsolete_sk(skill)
  return skill == "Charms" or skill == "Slings" or skill == "Bows" or skill == "Crossbows" or skill == "Stabbing" or skill == "Traps"
end

local function is_spell_sk(skill)
  return skill == "Spellcasting" or skill == "Conjurations" or skill == "Hexes" or skill == "Summonings" or skill == "Necromancy" or skill == "Translocations" or skill == "Fire Magic" or skill == "Ice Magic" or skill == "Air Magic" or skill == "Earth Magic" or skill == "Alchemy"
end

local function species_sorted(include_obsolete)
  include_obsolete = include_obsolete or false
  local species = {}
  for sp in pairs(data) do
    if not is_colored_draconian(sp) and (include_obsolete or not is_obsolete(sp)) then
      table.insert(species, sp)
    end
  end
  table.sort(species)
  return species
end

local function skill_average(skill)
  local count = 0
  local sum = 0
  for name, sp in pairs(data) do
    if sp.Aptitudes[skill] and not is_colored_draconian(name) and name ~= "Gnoll" and (is_obsolete_sk(skill) or not is_obsolete(name)) and (name ~= "Djinni" or not is_spell_sk(skill)) then
      count = count + 1
      sum = sum + sp.Aptitudes[skill]
    end
  end
  return string.format("%.3f", sum / count)
end
 
function p.aptitude(frame)
  local sp = frame.args[1]
  local sk = frame.args[2]
  if not sp or not sk then
    return ""
  end
  if sp == "Average" then
    return skill_average(sk)
  else
    return data[sp].Aptitudes[sk] or "N/A"
  end
end

function p.skill_table(frame)
  local browser_width = frame.args[2]
  browser_width = tonumber(browser_width) or 50
  local skill = name_arg(frame)
  local headers = {}
  local species = species_sorted(is_obsolete_sk(skill))

  local sp_headers_1 = {}
  local sp_headers_2 = {}
  for i, sp in ipairs(species) do
    local header = ("'''[[%s|%s]]'''"):format(sp, data[sp].Abbrev)
    if i<browser_width then
      table.insert(sp_headers_1, header)
    else
      table.insert(sp_headers_2, header)
    end
  end
  
  local sk_headers_1 = {}
  local sk_headers_2 = {}
  for i, sp in ipairs(species) do
    local header = ("%s"):format(data[sp].Aptitudes[skill] or "N/A")
    if i<browser_width then
      table.insert(sk_headers_1, header)
    else
      table.insert(sk_headers_2, header)
    end
  end

  local result = [[{| class="wikitable" border="1"
|-
|]]
  result = result .. table.concat(sp_headers_1, "\n|")
  result = result .. "\n|-\n| "
  result = result .. table.concat(sk_headers_1, "\n| ")
  if next(sp_headers_2) then
    result = result .. "\n|-\n|"
    result = result .. table.concat(sp_headers_2, "\n|")
    result = result .. "\n|-\n| "
    result = result .. table.concat(sk_headers_2, "\n| ")
  end
  result = result .. "\n|}"
  return result
end

function p.skill_draconian_exceptions(frame)
  local skill = name_arg(frame)
  local normal = data['Draconian'].Aptitudes[skill]
  local result = ''
  for name, species in pairs(data) do
    if is_colored_draconian(name) and (is_obsolete_sk(skill) or not is_obsolete(name)) and species.Aptitudes[skill] ~= normal then
      local col = name:match("^%a*")
      result = result .. '* [[Draconian#' .. col .. '|' .. col .. ' draconian]]s get ' .. species.Aptitudes[skill] .. '.\n'
    end
  end
  return result
end

local function aptitude_chart(skills, header)
  local result = header

  -- constants used by sort_key
  local a_ord = string.byte('a')
  local z_ord = string.byte('z')
  local aa_ord = string.byte('A')
  -- generates the table keys
  local function sort_key(i)
    local result
    if i > z_ord - a_ord then
      i = i - (z_ord - a_ord) - 1
      result = '!' .. string.char(aa_ord + i)
    else
      result = '"' .. string.char(a_ord + i)
    end
    return result
  end

  local i = 0
  for _, sp in ipairs(species_sorted()) do
    result = result .. '|<span style="display:none;">' .. sort_key(i) .. '</span>' .. sp .. "\n"
    for _, sk in ipairs(skills) do
      result = result .. "||" .. (data[sp].Aptitudes[sk] or "N/A") .. "\n"
    end
    result = result .. "|-\n"
    i = i + 1
  end
  result = result .. "|}"
  return result
end

function p.aptitude_chart_general(frame)
  local skills = {'Armour', 'Dodging',
   'Shields', 'Stealth', 'Invocations', 'Evocations', 'Shapeshifting', 'Hit Points', 'Magic Points', 'Experience'}
  local header = [=[
{| class="wikitable sortable" style="font-size:75%" border=1
! scope="col" | [[Species]]
! scope="col" | [[Armour (skill)|Arm]]
! scope="col" | [[Dodging|Ddg]]
! scope="col" | [[Shields (skill)|Shd]]
! scope="col" | [[Stealth|Sth]]
! scope="col" | [[Invocations|Inv]]
! scope="col" | [[Evocations|Evo]]
! scope="col" | [[Shapeshifting|Shp]]
! scope="col" | [[HP]]
! scope="col" | [[MP]]
! scope="col" | [[Exp]]
|-
]=]
  return aptitude_chart(skills, header)
end

function p.aptitude_chart_combat(frame)
  local skills = {'Fighting', 'Maces & Flails',
   'Axes', 'Polearms', 'Staves', 'Unarmed Combat', 'Throwing', 'Short Blades', 'Long Blades', 'Ranged Weapons'}
  local header = [=[
{| class="wikitable sortable" style="font-size:75%" border=1
! scope="col" | [[Species]]
! scope="col" | [[Fighting|Fgt]]
! scope="col" | [[Maces &amp; Flails|M&amp;F]]
! scope="col" | [[Axes|Axs]]
! scope="col" | [[Polearms|Pla]]
! scope="col" | [[Staves|Stv]]
! scope="col" | [[Unarmed Combat|UC]]
! scope="col" | [[Throwing|Thr]]
! scope="col" | [[Short Blades|SBl]]
! scope="col" | [[Long Blades|LBl]]
! scope="col" | [[Ranged Weapons|RW]]
|-
]=]
  return aptitude_chart(skills, header)
end

function p.aptitude_chart_magic(frame)
  local skills = {'Spellcasting', 'Conjurations', 'Hexes',
   'Summonings', 'Necromancy', 'Translocations', 'Alchemy', 
   'Fire Magic', 'Ice Magic', 'Air Magic', 'Earth Magic'}
  local header = [=[
{| class="wikitable sortable" style="font-size:75%" border=1
! scope="col" | [[Species]]
! scope="col" | [[Spellcasting|Spc]]
! scope="col" | [[Conjurations|Coj]]
! scope="col" | [[Hexes|Hex]]
! scope="col" | [[Summonings|Sum]]
! scope="col" | [[Necromancy|Nec]]
! scope="col" | [[Translocations|Trl]]
! scope="col" | [[Alchemy|Alc]]
! scope="col" | [[Fire Magic|Fir]]
! scope="col" | [[Ice Magic|Ice]]
! scope="col" | [[Air Magic|Air]]
! scope="col" | [[Earth Magic|Ear]]
|-
]=]
  return aptitude_chart(skills, header)
end

return p