• Welcome to the Kancolle Wiki!
  • If you have any questions regarding site content, account registration, etc., please visit the KanColle Wiki Discord

Difference between revisions of "Module:KanmusuModule"

From Kancolle Wiki
Jump to navigation Jump to search
Line 1: Line 1:
local U = require('Module:Core')
+
local U = require("Module:Core")
  
local function format_buildtime(minutes)
+
-- Some formatting
return U.format{ "${hours}:${minutes:2}", hours = math.floor(minutes / 60), minutes = minutes % 60 }
 
end
 
  
local ShipList = {}
+
local function formatBuildtime(minutes)
 
+
  return U.format {"${hours}:${minutes:2}", hours = math.floor(minutes / 60), minutes = minutes % 60}
function ShipList.findID(frame)
 
    for id, data in pairs(ShipList.KanmusuData) do
 
        if ShipList.KanmusuData[id].name[3] == frame.args[1] then
 
        return id
 
        end
 
    end
 
    return "NotInDB"
 
 
end
 
end
  
function ShipList.getSortedIDList()
+
local function formatTooltip(content, title)
    local IDList = {}
+
  return tostring(mw.html.create("span"):attr("title", title):addClass("explain"):wikitext(content))
    for id, data in pairs(ShipList.KanmusuData) do
 
        IDList[#IDList + 1] = id
 
        local x = #IDList
 
        while x > 1 and IDList[x] < IDList[x - 1] do
 
            IDList[x - 1], IDList[x] = IDList[x], IDList[x - 1]
 
            x = x - 1
 
        end
 
    end
 
    return IDList
 
 
end
 
end
  
function ShipList.TotalAircraft(frame)
+
-- Some calculations
    local shipID = frame.args[1]
 
    -- if tonumber(shipID) == nil then
 
    --    shipID = ShipList.findID(frame)
 
    -- end
 
    local ship = ShipList.KanmusuData[shipID]
 
    local total = 0
 
    if ship.aircraft ~= "" then
 
    for i, planes in pairs(ship.aircraft) do
 
    if ship.aircraft[i] == nil or ship.aircraft[i] == "" then
 
    total = total + 0 
 
else
 
total = total + ship.aircraft[i]
 
end
 
end
 
end
 
    return total
 
end
 
  
function ShipList.getWikiPage(id)
+
local function getTotalAircraft(ship)
    --finding name of wiki page of ship
+
  local total = 0
    shipname = ShipList.KanmusuData[id]["name"][3]
+
  if ship.aircraft ~= "" then
    pagename = shipname
+
    for i, _ in pairs(ship.aircraft) do
    if string.sub(id,1,-2) == "Mist" then   -- fleet of fog check
+
      if ship.aircraft[i] == nil or ship.aircraft[i] == "" then
    if string.sub(id, -1) == '1' then
+
        total = total + 0
    pagename = 'Iona_(fog)'
+
      else
    elseif string.sub(id, -1) == '2' then
+
        total = total + ship.aircraft[i]
    pagename = 'Takao_(fog)'
+
      end
    elseif string.sub(id, -1) == '3' then
+
    end
    pagename = 'Haruna_(fog)'
+
  end
else
+
  return total
pagename = 'Fleet of Fog'
 
end
 
else
 
shipbasename = mw.text.split(shipname, '%s')[1]
 
--Prinz/Graf/Teste check (for ship names that are 2 or more words)
 
if mw.text.split(shipname, '%s')[2] ~= nil and not (mw.text.split(shipname, '%s')[2] == "Kai" or
 
mw.text.split(shipname, '%s')[2] == "A" or mw.text.split(shipname, '%s')[2] == "Zwei" or
 
mw.text.split(shipname, '%s')[2] == "Drei" or mw.text.split(shipname, '%s')[2] == "Due") then
 
shipbasename = shipbasename .. ' ' .. mw.text.split(shipname, '%s')[2]
 
end
 
pagename = shipbasename
 
end
 
return pagename
 
 
end
 
end
 
ShipList.KanmusuData = mw.loadData('Module:Data/Ship')
 
 
local shipdb = ShipList
 
 
local shipmodule = {}
 
 
shipmodule.data = shipdb.KanmusuData
 
  
 
local function getMarriedHp(hp, maxHp)
 
local function getMarriedHp(hp, maxHp)
Line 87: Line 31:
 
end
 
end
  
local function tooltip(content, title)
+
-- The ship infobox stuff...
  return tostring(mw.html.create('span'):attr('title', title):addClass('explain'):wikitext(content))
 
end
 
 
 
function shipmodule.getIDNum(frame)
 
    local shipNum = frame.args[1]
 
    -- Getting ship ID, number, & info
 
    if (tonumber(string.sub(shipNum, 1, 3)) == nil and string.sub(shipNum, 1, 4) ~= "Mist" ) then -- if given a name instead of ID, this searches the db for the ship's corresponding ID
 
    shipNum = shipdb.findID(frame)
 
    end
 
    return shipNum
 
end
 
  
function shipmodule.KanmusuInfo(frame) -- Kanmusu Info Template
+
local function renderStats(ship, shipNum)
    local shipNum = shipmodule.getIDNum(frame)
+
  local shipName = ship.name[3]
    local shipInfo = assert(shipmodule.data[shipNum], "KanMusu ID " .. shipNum .. " doesn't have a database entry")
+
  local CardImg = '<div class="top-image">[[File:Ship Card ' .. shipName .. ".png|218x300px|link=]]</div>"
    local upperTable = shipmodule.makeStatBox(frame)
+
  local CardDmgImg = '<div class="bottom-image">[[File:Ship Card ' .. shipName .. " Damaged.png|218x300px|link=]]</div>"
    local DetailTable = shipmodule.EquipmentBox(frame) .. '<table style="width: 100%">' .. shipmodule.ModernizationBox(frame) .. shipmodule.getArtVoice(frame) .. '</table>'
+
  local BannerImg = '<div class="top-image">[[File:Ship Banner ' .. shipName .. ".png|link=]]</div>"
    local shipInfoBox = '<div style="display: inline-block; vertical-align: top;"><table style="{{border-radius|10px 10px 10px 10px}} border: 1px solid #aaaaaa; min-width: 495px">'
+
  local BannerDmgImg = '<div class="bottom-image">[[File:Ship Banner ' .. shipName .. " Damaged.png|link=]]</div>"
    shipInfoBox = shipInfoBox .. '<tr><td>' .. upperTable .. '</td></tr>'
+
  local Cards =
     shipInfoBox = shipInfoBox .. '<tr><td>' .. DetailTable .. '</td></tr></table></div>' .. shipmodule.createCategories(frame)
+
     '<td rowspan="10" class="double-image" style="width:218px;height:300px">' .. CardImg .. CardDmgImg .. "</td>"
    return shipInfoBox
+
  local Banners =
end
+
     '<td colspan="3" class="double-image" style="width:240px;height:60px">' .. BannerImg .. BannerDmgImg .. "</td>"
 
+
  local sortNo = ship.sortno or U.split(shipNum, "-")[1] or "?"
function shipmodule.makeStatBox(frame)
+
  local row1 = "<tr>" .. Cards .. '<th style="text-align: center;">' .. sortNo .. "</th>" .. Banners .. "</tr>"
    local shipNum = shipmodule.getIDNum(frame)
+
  -- Formatting Japanese
 
+
  local kanji, form
     local shipInfo = assert(shipmodule.data[shipNum], "KanMusu ID " .. shipNum .. " doesn't have a database entry")
+
  local formNum = mw.ustring.find(ship["name"][1], "[乙改甲航]")
 
+
  if formNum == nil then
local shipName = shipInfo.name[3]
+
    if mw.ustring.find(ship["name"][1], "%szwei") ~= nil then
    local CardImg = '<div class="top-image">[[File:Ship Card ' .. shipName .. '.png|218x300px|link=]]</div>'
+
      formNum = mw.ustring.find(ship["name"][1], "%szwei")
    local CardDmgImg = '<div class="bottom-image">[[File:Ship Card ' .. shipName .. ' Damaged.png|218x300px|link=]]</div>'
+
      kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
    local BannerImg = '<div class="top-image">[[File:Ship Banner ' .. shipName .. '.png|link=]]</div>'
+
      form = "&#32;zwei"
    local BannerDmgImg = '<div class="bottom-image">[[File:Ship Banner ' .. shipName .. ' Damaged.png|link=]]</div>'
+
    elseif mw.ustring.find(ship["name"][1], "%sdrei") ~= nil then
 
+
      formNum = mw.ustring.find(ship["name"][1], "%sdrei")
    local Cards = '<td rowspan="10" class="double-image" style="width:218px;height:300px">' .. CardImg .. CardDmgImg .. '</td>'
+
      kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
    local Banners = '<td colspan="3" class="double-image" style="width:240px;height:60px">' .. BannerImg .. BannerDmgImg .. '</td>'
+
      form = "&#32;drei"
    -- frame:extensionTag('slideshow', CardImg .. CardDmgImg, { sequence = 'forward', transition = 'fade', refresh = '10000', center = 'true' })
+
    elseif mw.ustring.find(ship["name"][1], "%sdue") ~= nil then
    -- frame:extensionTag('slideshow', BannerImg .. BannerDmgImg, { sequence = 'forward', transition = 'fade', refresh = '10000', center = 'true' })
+
      formNum = mw.ustring.find(ship["name"][1], "%sdue")
 
+
      kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
     local sortNo = shipInfo.sortno or U.split(shipNum, '-')[1] or '?'
+
      form = "&#32;due"
    local row1 = '<tr>' .. Cards .. '<th style="text-align: center;">' .. sortNo .. '</th>' .. Banners .. '</tr>'
+
     elseif mw.ustring.find(ship["name"][1], "%sдва") ~= nil then
 
+
      formNum = mw.ustring.find(ship["name"][1], "%sдва")
     -- Formatting Japanese
+
      kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
    local kanji, form
+
      form = "&#32;два"
local formNum = mw.ustring.find(shipmodule.data[shipNum]["name"][1], "[乙改甲航]")
+
     elseif mw.ustring.find(ship["name"][1], "%sMk.II") ~= nil then
if formNum == nil then  
+
      if mw.ustring.find(ship["name"][1], "%sMk.II Mod.2") ~= nil then
if mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%szwei") ~= nil then
+
        formNum = mw.ustring.find(ship["name"][1], "%sMk.II Mod.2")
formNum = mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%szwei")
+
        kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
kanji = mw.ustring.sub(shipmodule.data[shipNum]["name"][1], 1, formNum - 1)
+
        form = "&#32;Mk.II Mod.2"
form = "&#32;zwei"
+
      else
elseif mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sdrei") ~= nil then
+
        formNum = mw.ustring.find(ship["name"][1], "%sMk.II")
formNum = mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sdrei")
+
        kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
kanji = mw.ustring.sub(shipmodule.data[shipNum]["name"][1], 1, formNum - 1)
+
        form = "&#32;Mk.II"
form = "&#32;drei"
+
      end
elseif mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sdue") ~= nil then
+
    elseif mw.ustring.find(ship["name"][1], "%sреволюция") ~= nil then -- Gangut "Kai" exception
formNum = mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sdue")
+
      kanji = mw.text.split(ship["name"][1], "%s")[1] .. "<br/>" .. mw.text.split(ship["name"][1], "%s")[2]
kanji = mw.ustring.sub(shipmodule.data[shipNum]["name"][1], 1, formNum - 1)
+
      form = ""
form = "&#32;due"
 
elseif mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sдва") ~= nil then
 
formNum = mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sдва")
 
kanji = mw.ustring.sub(shipmodule.data[shipNum]["name"][1], 1, formNum - 1)
 
form = "&#32;два"
 
elseif mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sMk.II") ~= nil then
 
            if mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sMk.II Mod.2") ~= nil then
 
                formNum = mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sMk.II Mod.2")
 
    kanji = mw.ustring.sub(shipmodule.data[shipNum]["name"][1], 1, formNum - 1)
 
    form = "&#32;Mk.II Mod.2"
 
            else
 
    formNum = mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sMk.II")
 
    kanji = mw.ustring.sub(shipmodule.data[shipNum]["name"][1], 1, formNum - 1)
 
    form = "&#32;Mk.II"
 
                end
 
elseif mw.ustring.find(shipmodule.data[shipNum]["name"][1], "%sреволюция") ~= nil then -- Gangut "Kai" exception
 
kanji = mw.text.split(shipmodule.data[shipNum]["name"][1], "%s")[1] .. '<br/>' .. mw.text.split(shipmodule.data[shipNum]["name"][1], "%s")[2]
 
form = ""
 
else
 
kanji = shipmodule.data[shipNum]["name"][1]
 
form = ""
 
end
 
else
 
kanji = mw.ustring.sub(shipmodule.data[shipNum]["name"][1], 1, formNum - 1)
 
form = mw.ustring.sub(shipmodule.data[shipNum]["name"][1], formNum , -1)
 
end
 
 
local JaName = ""
 
if shipNum == "147" or shipNum == "311" or shipNum == "312" or shipNum == "313" or shipNum == "313a" or shipNum == "316" then --Russian ship markup
 
JaName = '<ruby lang="ru"><rb>' .. kanji .. '<span lang="ru">' .. form .. '</span>' .. '</rb><rp> (</rp><rt lang="ja">' .. shipmodule.data[shipNum]["name"][2] .. '</rt><rp>) </rp></ruby>'
 
else
 
if shipInfo.name[2] then
 
JaName = '<ruby lang="ja"><rb>' .. kanji .. '<span>' .. form .. '</span>' .. '</rb><rp> (</rp><rt>' .. shipInfo.name[2] .. '</rt><rp>) </rp></ruby>'
 
else
 
JaName = '<ruby lang="ja"><rb>' .. kanji .. '<span>' .. form .. '</span>' .. '</rb></ruby>'
 
end
 
end
 
 
 
    -- Summary of basic ship info
 
    local isCVE = shipInfo.type == 'Light Carrier' and type(shipInfo.asw) == 'table' and type(shipInfo.asw[1]) == 'number' and shipInfo.asw[1] > 0
 
    local shipType = isCVE and string.format('<span class="explain" title="CVE">%s[[Category:Escort Carriers]]</span>', shipInfo.type) or shipInfo.type
 
    local row2 = '<tr><th colspan="2">' .. JaName .. '</th><th colspan="2">' .. shipInfo.name[3] .. '</th></tr>'
 
    local row3 = '<tr><td colspan="4" style="text-align: center;">' .. shipInfo.class .. ' Class ' .. shipType .. '</td></tr>'
 
    local row4 = '<tr><td colspan="4"><hr style="border: 0; height: 1px; background-image: linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));" /></td></tr>'
 
 
 
    -- Ship stats table
 
    local statLabel = '<th style="width: 65px; {{border-radius|12px 4px 4px 12px}} padding-left: 5px; padding-right: 5px; background-color: #eae1d1; color: #a3965c; text-align: right; vertical-align: baseline;">'
 
    local statBox = '<td style="{{border-radius|4px 12px 12px 4px}} padding-left: 5px; padding-right: 5px; border: 1px solid #a3965c; text-align: left; vertical-align: baseline;">'
 
 
 
    local hp = shipmodule.data[shipNum]["hp"][1]
 
    local maxHp = shipmodule.data[shipNum]["hp"][2]
 
    local HPinfo
 
    if maxHp then
 
      local marriedHp = getMarriedHp(hp, maxHp)
 
      local maxModHp = math.min(hp + 2, maxHp)
 
      local maxModMarriedHp = math.min(marriedHp + 2, maxHp)
 
      local hpSpan1 = hp == maxModHp and hp or tooltip(hp, string.format('%d with HP modernization', maxModHp))
 
      local hpSpan2 = tooltip(marriedHp, marriedHp == maxModMarriedHp and 'Married' or string.format('Married, %d with HP modernization', maxModMarriedHp))
 
      HPinfo = statLabel .. 'HP [[File:IcoHP.png|HP]]</th>' .. statBox .. hpSpan1 .. '→' .. hpSpan2 .. '</td>'
 
    else
 
      HPinfo = statLabel .. 'HP [[File:IcoHP.png|HP]]</th>' .. statBox .. hp .. '</td>'
 
    end
 
 
 
    local FPinfo = statLabel .. 'FP [[File:IcoAtk.png|Firepower]]</th>' .. statBox .. shipmodule.data[shipNum]["fp"][1] .. '→' .. shipmodule.data[shipNum]["fp"][2] .. '</td>'
 
 
 
    local row5 = '<tr>' .. HPinfo .. FPinfo .. '</tr>'
 
 
 
    -- Armor & Torpedo
 
    local Armorinfo = statLabel .. 'ARM [[File:IcoArmor.png|Armor]]</th>' .. statBox .. shipmodule.data[shipNum]["armor"][1] .. '→' .. shipmodule.data[shipNum]["armor"][2] .. '</td>'
 
    local Torpedoinfo = statLabel .. 'TORP [[File:IcoTorpedo.png|Torpedo]]</th>' .. statBox
 
    if shipmodule.data[shipNum]["torpedo"] == 0 then
 
        Torpedoinfo = Torpedoinfo .. shipmodule.data[shipNum]["torpedo"]
 
    else
 
        Torpedoinfo = Torpedoinfo .. shipmodule.data[shipNum]["torpedo"][1] .. '→' .. shipmodule.data[shipNum]["torpedo"][2]
 
    end
 
 
 
    local row6 = '<tr>' .. Armorinfo .. Torpedoinfo .. '</tr>'
 
 
 
    -- Evasion & AA
 
    local Evasioninfo = statLabel .. 'EVA [[File:IcoEvasion.png|Evasion]]</th>' .. statBox .. shipmodule.data[shipNum]["evasion"][1] .. '→' .. shipmodule.data[shipNum]["evasion"][2] .. '</td>'
 
    local AAinfo = statLabel .. 'AA [[File:IcoAA.png|Anti-Air]]</th>' .. statBox
 
    if shipmodule.data[shipNum]["aa"] == 0 then
 
        AAinfo = AAinfo .. shipmodule.data[shipNum]["aa"]
 
 
     else
 
     else
        AAinfo = AAinfo .. shipmodule.data[shipNum]["aa"][1] .. '→' .. shipmodule.data[shipNum]["aa"][2]
+
      kanji = ship["name"][1]
 +
      form = ""
 
     end
 
     end
 
+
  else
     local row7 = '<tr>' .. Evasioninfo .. AAinfo .. '</tr>'
+
     kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
 
+
    form = mw.ustring.sub(ship["name"][1], formNum, -1)
     -- Planes & ASW
+
  end
     local aircraftTotal = shipdb.TotalAircraft(frame)
+
  local JaName = ""
    local Planeinfo = statLabel .. 'PLA [[File:IcoAircraft.png|Aircraft]]</th>' .. statBox .. aircraftTotal .. '</td>'
+
  if
    local ASWinfo = statLabel .. 'ASW [[File:IcoASW.png|Anti-Submarine Warfare]]</th>' .. statBox
+
     shipNum == "147" or shipNum == "311" or shipNum == "312" or shipNum == "313" or shipNum == "313a" or
     if shipmodule.data[shipNum]["asw"] == 0 then
+
      shipNum == "316"
         ASWinfo = ASWinfo .. shipmodule.data[shipNum]["asw"]
+
  then --Russian ship markup
 +
     JaName =
 +
      '<ruby lang="ru"><rb>' ..
 +
      kanji ..
 +
        '<span lang="ru">' ..
 +
          form .. "</span>" .. '</rb><rp> (</rp><rt lang="ja">' .. ship["name"][2] .. "</rt><rp>) </rp></ruby>"
 +
  else
 +
     if ship.name[2] then
 +
      JaName =
 +
        '<ruby lang="ja"><rb>' ..
 +
         kanji .. "<span>" .. form .. "</span>" .. "</rb><rp> (</rp><rt>" .. ship.name[2] .. "</rt><rp>) </rp></ruby>"
 
     else
 
     else
        ASWinfo = ASWinfo .. shipmodule.data[shipNum]["asw"][1] .. '→' .. shipmodule.data[shipNum]["asw"][2]
+
      JaName = '<ruby lang="ja"><rb>' .. kanji .. "<span>" .. form .. "</span>" .. "</rb></ruby>"
 
     end
 
     end
 
+
  end
     local row8 = '<tr>' .. Planeinfo .. ASWinfo .. '</tr>'
+
  -- Summary of basic ship info
 
+
  local isCVE =
     -- Speed & LOS
+
    ship.type == "Light Carrier" and type(ship.asw) == "table" and type(ship.asw[1]) == "number" and ship.asw[1] > 0
    local Speedinfo = statLabel .. 'SPD [[File:IcoSpeed.png|Speed]]</th>' .. statBox .. shipmodule.data[shipNum]["spd"] .. '</td>'
+
  local shipType =
    local LOSinfo = statLabel .. 'LOS [[File:IcoLOS.png|Line of Sight]]</th>' .. statBox .. shipmodule.data[shipNum]["los"][1] .. '' .. shipmodule.data[shipNum]["los"][2] .. '</td>'
+
     isCVE and string.format('<span class="explain" title="CVE">%s[[Category:Escort Carriers]]</span>', ship.type) or
 
+
    ship.type
    local row9 = '<tr>' .. Speedinfo .. LOSinfo .. '</tr>'
+
  local row2 = '<tr><th colspan="2">' .. JaName .. '</th><th colspan="2">' .. ship.name[3] .. "</th></tr>"
 
+
  local row3 = '<tr><td colspan="4" style="text-align: center;">' .. ship.class .. " Class " .. shipType .. "</td></tr>"
    -- Range & Luck
+
  local row4 =
    local Rangeinfo = statLabel .. 'RGE [[File:IcoRange.png|Range]]</th>' .. statBox .. shipmodule.data[shipNum]["range"] .. '</td>'
+
    '<tr><td colspan="4"><hr style="border: 0; height: 1px; background-image: linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));" /></td></tr>'
    local Luckinfo = statLabel .. 'LUK [[File:IcoLuck.png|Luck]]</th>' .. statBox .. shipmodule.data[shipNum]["luck"][1] .. '' .. shipmodule.data[shipNum]["luck"][2] .. '</td>'
+
  -- Ship stats table
 
+
  local statLabel =
    local row10 = '<tr>' .. Rangeinfo .. Luckinfo .. '</tr>'
+
    '<th style="width: 65px; {{border-radius|12px 4px 4px 12px}} padding-left: 5px; padding-right: 5px; background-color: #eae1d1; color: #a3965c; text-align: right; vertical-align: baseline;">'
    local StatTable = '<table>' .. row1 .. row2 .. row3 .. row4 .. row5 .. row6 .. row7 .. row8 .. row9 .. row10 .. '</table>'
+
  local statBox =
    return StatTable
+
    '<td style="{{border-radius|4px 12px 12px 4px}} padding-left: 5px; padding-right: 5px; border: 1px solid #a3965c; text-align: left; vertical-align: baseline;">'
 +
  local hp = ship["hp"][1]
 +
  local maxHp = ship["hp"][2]
 +
  local HPinfo
 +
  if maxHp then
 +
    local marriedHp = getMarriedHp(hp, maxHp)
 +
    local maxModHp = math.min(hp + 2, maxHp)
 +
    local maxModMarriedHp = math.min(marriedHp + 2, maxHp)
 +
    local hpSpan1 = hp == maxModHp and hp or formatTooltip(hp, string.format("%d with HP modernization", maxModHp))
 +
    local hpSpan2 =
 +
      formatTooltip(
 +
      marriedHp,
 +
      marriedHp == maxModMarriedHp and "Married" or string.format("Married, %d with HP modernization", maxModMarriedHp)
 +
    )
 +
    HPinfo = statLabel .. "HP [[File:IcoHP.png|HP]]</th>" .. statBox .. hpSpan1 .. "→" .. hpSpan2 .. "</td>"
 +
  else
 +
    HPinfo = statLabel .. "HP [[File:IcoHP.png|HP]]</th>" .. statBox .. hp .. "</td>"
 +
  end
 +
  local FPinfo =
 +
     statLabel .. "FP [[File:IcoAtk.png|Firepower]]</th>" .. statBox .. ship["fp"][1] .. "→" .. ship["fp"][2] .. "</td>"
 +
  local row5 = "<tr>" .. HPinfo .. FPinfo .. "</tr>"
 +
  -- Armor & Torpedo
 +
  local Armorinfo =
 +
    statLabel ..
 +
    "ARM [[File:IcoArmor.png|Armor]]</th>" .. statBox .. ship["armor"][1] .. "→" .. ship["armor"][2] .. "</td>"
 +
  local Torpedoinfo = statLabel .. "TORP [[File:IcoTorpedo.png|Torpedo]]</th>" .. statBox
 +
  if ship["torpedo"] == 0 then
 +
    Torpedoinfo = Torpedoinfo .. ship["torpedo"]
 +
  else
 +
    Torpedoinfo = Torpedoinfo .. ship["torpedo"][1] .. "→" .. ship["torpedo"][2]
 +
  end
 +
  local row6 = "<tr>" .. Armorinfo .. Torpedoinfo .. "</tr>"
 +
  -- Evasion & AA
 +
  local Evasioninfo =
 +
    statLabel ..
 +
    "EVA [[File:IcoEvasion.png|Evasion]]</th>" .. statBox .. ship["evasion"][1] .. "→" .. ship["evasion"][2] .. "</td>"
 +
  local AAinfo = statLabel .. "AA [[File:IcoAA.png|Anti-Air]]</th>" .. statBox
 +
  if ship["aa"] == 0 then
 +
    AAinfo = AAinfo .. ship["aa"]
 +
  else
 +
    AAinfo = AAinfo .. ship["aa"][1] .. "→" .. ship["aa"][2]
 +
  end
 +
  local row7 = "<tr>" .. Evasioninfo .. AAinfo .. "</tr>"
 +
  -- Planes & ASW
 +
  local aircraftTotal = getTotalAircraft(ship)
 +
  local Planeinfo = statLabel .. "PLA [[File:IcoAircraft.png|Aircraft]]</th>" .. statBox .. aircraftTotal .. "</td>"
 +
  local ASWinfo = statLabel .. "ASW [[File:IcoASW.png|Anti-Submarine Warfare]]</th>" .. statBox
 +
  if ship["asw"] == 0 then
 +
    ASWinfo = ASWinfo .. ship["asw"]
 +
  else
 +
    ASWinfo = ASWinfo .. ship["asw"][1] .. "→" .. ship["asw"][2]
 +
  end
 +
  local row8 = "<tr>" .. Planeinfo .. ASWinfo .. "</tr>"
 +
  -- Speed & LOS
 +
  local Speedinfo = statLabel .. "SPD [[File:IcoSpeed.png|Speed]]</th>" .. statBox .. ship["spd"] .. "</td>"
 +
  local LOSinfo =
 +
    statLabel ..
 +
    "LOS [[File:IcoLOS.png|Line of Sight]]</th>" .. statBox .. ship["los"][1] .. "" .. ship["los"][2] .. "</td>"
 +
  local row9 = "<tr>" .. Speedinfo .. LOSinfo .. "</tr>"
 +
  -- Range & Luck
 +
  local Rangeinfo = statLabel .. "RGE [[File:IcoRange.png|Range]]</th>" .. statBox .. ship["range"] .. "</td>"
 +
  local Luckinfo =
 +
    statLabel .. "LUK [[File:IcoLuck.png|Luck]]</th>" .. statBox .. ship["luck"][1] .. "" .. ship["luck"][2] .. "</td>"
 +
  local row10 = "<tr>" .. Rangeinfo .. Luckinfo .. "</tr>"
 +
  local StatTable =
 +
    "<table>" .. row1 .. row2 .. row3 .. row4 .. row5 .. row6 .. row7 .. row8 .. row9 .. row10 .. "</table>"
 +
  return StatTable
 
end
 
end
  
function shipmodule.EquipmentBox(frame)
+
local function renderEquipment(ship)
    local shipNum = shipmodule.getIDNum(frame)
+
  local equipHeader = ""
 
+
  local planeStyle = '<td style="width: 25%; white-space: nowrap; text-align: center; vertical-align: top;">'
    local shipInfo = assert(shipmodule.data[shipNum], "KanMusu ID " .. shipNum .. " doesn't have a database entry")
+
  local equipStyle = ""
 
+
  if ship["aircraft"] ~= "" then
    -- Equipment table
+
    local equipHeader1 =
    local equipHeader = ''
+
      '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #efe6d7; color: #a3965c;">Aircraft</th>'
    local planeStyle = '<td style="width: 25%; white-space: nowrap; text-align: center; vertical-align: top;">'
+
    local equipHeader2 =
    local equipStyle = ''
+
      '<th style="width: 75%; white-space: nowrap; {{border-radius|4px 12px 12px 4px}} background-color: #efe6d7; color: #a3965c; vertical-align: baseline;">Equipment</th>'
    if shipmodule.data[shipNum]["aircraft"] ~= "" then
+
    equipHeader = equipHeader1 .. equipHeader2
        equipHeader1 = '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #efe6d7; color: #a3965c;">Aircraft</th>'
+
    equipStyle = '<td style="width: 75%; max-width: 375px; text-align: center; vertical-align: baseline;">'
        equipHeader2 = '<th style="width: 75%; white-space: nowrap; {{border-radius|4px 12px 12px 4px}} background-color: #efe6d7; color: #a3965c; vertical-align: baseline;">Equipment</th>'
+
  else
        equipHeader = equipHeader1 .. equipHeader2
+
    equipHeader =
        equipStyle = '<td style="width: 75%; max-width: 375px; text-align: center; vertical-align: baseline;">'
+
      '<th style="white-space: nowrap; {{border-radius|12px 12px 12px 12px}} background-color: #efe6d7; color: #a3965c; vertical-align: baseline;">Equipment</th>'
 +
    equipStyle = '<td style="white-space: nowrap; text-align: center; vertical-align: baseline;">'
 +
  end
 +
  local numRows = math.max(4, U.isize(ship["equip"]))
 +
  local equipTable = ""
 +
  for i = 1, numRows, 1 do
 +
    local equipRow = "<tr>"
 +
    if ship["aircraft"] ~= "" then
 +
      if ship["aircraft"][i] ~= nil then
 +
        equipRow = equipRow .. planeStyle .. ship["aircraft"][i] .. "</td>" .. equipStyle
 +
      else
 +
        equipRow = equipRow .. planeStyle .. "</td>" .. equipStyle
 +
      end
 +
      if ship["equip"] ~= "" then
 +
        if ship["equip"][i] == "" or ship["equip"][i] == "Unequipped" then
 +
          equipRow = equipRow .. "-Unequipped-</td></tr>"
 +
        elseif ship["equip"][i] == nil then
 +
          equipRow = equipRow .. "''-Locked-''</td></tr>"
 +
        else
 +
          if string.find(ship["equip"][i], "%★") then
 +
            local a, b = string.match(ship["equip"][i], "^(.+)★(.+)$")
 +
            equipRow = equipRow .. "[[" .. a .. "|" .. a .. "★" .. b .. "]]</td></tr>"
 +
          else
 +
            equipRow = equipRow .. "[[" .. ship["equip"][i] .. "]]</td></tr>"
 +
          end
 +
        end
 +
      else
 +
        equipRow = equipRow .. "''-Locked-''</td></tr>"
 +
      end
 
     else
 
     else
        equipHeader = '<th style="white-space: nowrap; {{border-radius|12px 12px 12px 12px}} background-color: #efe6d7; color: #a3965c; vertical-align: baseline;">Equipment</th>'
+
      equipRow = equipRow .. equipStyle
        equipStyle = '<td style="white-space: nowrap; text-align: center; vertical-align: baseline;">'
+
      if ship["equip"] ~= "" then
    end
+
        if ship["equip"][i] == "" or ship["equip"][i] == "Unequipped" then
 
+
          equipRow = equipRow .. "-Unequipped-</td></tr>"
local numRows = math.max(4, U.isize(shipmodule.data[shipNum]["equip"]))
+
        elseif ship["equip"][i] == nil then
    local equipTable = ''
+
          equipRow = equipRow .. "''Locked''</td></tr>"
    for i = 1, numRows, 1 do
 
    local equipRow = '<tr>'
 
        if shipmodule.data[shipNum]["aircraft"] ~= "" then
 
        if shipmodule.data[shipNum]["aircraft"][i] ~= nil then
 
        equipRow = equipRow .. planeStyle .. shipmodule.data[shipNum]["aircraft"][i] .. '</td>' .. equipStyle
 
    else
 
    equipRow = equipRow .. planeStyle .. '</td>' .. equipStyle
 
    end
 
            if shipmodule.data[shipNum]["equip"] ~= "" then
 
                if shipmodule.data[shipNum]["equip"][i] == "" or shipmodule.data[shipNum]["equip"][i] == "Unequipped" then
 
                    equipRow = equipRow .. '-Unequipped-</td></tr>'
 
                elseif shipmodule.data[shipNum]["equip"][i] == nil then
 
                    equipRow = equipRow .. '\'\'-Locked-\'\'</td></tr>'
 
                else
 
                    if string.find(shipmodule.data[shipNum]["equip"][i], "%★") then
 
                        a,b = string.match(shipmodule.data[shipNum]["equip"][i], "^(.+)★(.+)$")
 
                        equipRow = equipRow .. '[[' .. a .. '|' .. a .. '★' .. b .. ']]</td></tr>'
 
                    else
 
                        equipRow = equipRow .. '[[' .. shipmodule.data[shipNum]["equip"][i] .. ']]</td></tr>'
 
                    end
 
                end
 
            else
 
                equipRow = equipRow .. '\'\'-Locked-\'\'</td></tr>'
 
            end
 
 
         else
 
         else
            equipRow = equipRow .. equipStyle
+
          if string.find(ship["equip"][i], "%★") then
            if shipmodule.data[shipNum]["equip"] ~= "" then
+
            local a, b = string.match(ship["equip"][i], "^(.+)★(.+)$")
                if shipmodule.data[shipNum]["equip"][i] == "" or shipmodule.data[shipNum]["equip"][i] == "Unequipped" then
+
            equipRow = equipRow .. "[[" .. a .. "|" .. a .. "" .. b .. "]]</td></tr>"
                    equipRow = equipRow .. '-Unequipped-</td></tr>'
+
          else
                elseif shipmodule.data[shipNum]["equip"][i] == nil then
+
            equipRow = equipRow .. "[[" .. ship["equip"][i] .. "]]</td></tr>"
                    equipRow = equipRow .. '\'\'Locked\'\'</td></tr>'
+
          end
                else
 
                    if string.find(shipmodule.data[shipNum]["equip"][i], "%★") then
 
                        a,b = string.match(shipmodule.data[shipNum]["equip"][i], "^(.+)★(.+)$")
 
                        equipRow = equipRow .. '[[' .. a .. '|' .. a .. '' .. b .. ']]</td></tr>'
 
                    else
 
                        equipRow = equipRow .. '[[' .. shipmodule.data[shipNum]["equip"][i] .. ']]</td></tr>'
 
                    end
 
                end
 
            else
 
                equipRow = equipRow .. '\'\'Locked\'\'</td></tr>'
 
            end
 
 
         end
 
         end
         equipTable = equipTable .. equipRow
+
      else
 +
         equipRow = equipRow .. "''Locked''</td></tr>"
 +
      end
 
     end
 
     end
     return '<table style="width: 100%">' .. equipHeader .. equipTable .. '</table>'
+
     equipTable = equipTable .. equipRow
 +
  end
 +
  return '<table style="width: 100%">' .. equipHeader .. equipTable .. "</table>"
 
end
 
end
  
function shipmodule.ModernizationBox(frame)
+
local function renderModernization(ship)
    local shipNum = shipmodule.getIDNum(frame)
+
  local RscHeader =
    local shipInfo = assert(shipmodule.data[shipNum], "KanMusu ID " .. shipNum .. " doesn't have a database entry")
+
     '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #3baef5; color: #ffffff; padding-left: 5px; padding-right: 5px; text-align: right;">'
 
+
  local RscData = '<td style="width: 25%; white-space: nowrap; text-align: center;">'
     local RscHeader = '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #3baef5; color: #ffffff; padding-left: 5px; padding-right: 5px; text-align: right;">'
+
  local RscData2 = '<td colspan="3" style="width: 75%; white-space: nowrap; text-align: center;">'
    local RscData = '<td style="width: 25%; white-space: nowrap; text-align: center;">'
+
  -- Construction info
    local RscData2 = '<td colspan="3" style="width: 75%; white-space: nowrap; text-align: center;">'
+
  local constrheader = ""
 
+
  local constrdata = ""
    -- Construction info
+
  if ship["remodellv"] ~= nil and ship["remodellv"] ~= "" then
    local constrheader = ''
+
    constrheader = "Remodel Level"
    local constrdata = ''
+
    constrdata = ship["remodellv"]
 
+
  else
    if shipInfo["remodellv"] ~= nil and shipInfo["remodellv"] ~= "" then
+
    constrheader = '<span class="explain-dash" title="h:mm">Build Time</span>'
        constrheader = 'Remodel Level'
+
    constrdata =
        constrdata = shipInfo["remodellv"]
+
      type(ship.buildtime) ~= "table" and "??" or
    else
+
      string.format(
        constrheader = '<span class="explain-dash" title="h:mm">Build Time</span>'
+
        "%s (%s)",
        constrdata = type(shipInfo.buildtime) ~= 'table' and '??' or string.format("%s (%s)", format_buildtime(shipInfo.buildtime[1]),
+
        formatBuildtime(ship.buildtime[1]),
        shipInfo.buildtime[2] and shipInfo.buildtime[3] and 'Normal, LSC' or shipInfo.buildtime[2] and 'Normal' or shipInfo.buildtime[3] and 'LSC' or 'Unbuildable')
+
        ship.buildtime[2] and ship.buildtime[3] and "Normal, LSC" or ship.buildtime[2] and "Normal" or
 +
          ship.buildtime[3] and "LSC" or
 +
          "Unbuildable"
 +
      )
 +
  end
 +
  local remodelinfo = ""
 +
  if ship.remodelreq and ship.remodelreq ~= "" then
 +
    remodelinfo =
 +
      string.format(
 +
      "[[File:IcoSteel.png|18px|Steel]] %d [[File:IcoAmmo.png|18px|Ammo]] %d",
 +
      ship.remodelreq[1],
 +
      ship.remodelreq[2]
 +
    )
 +
    if ship.remodelbp then
 +
      remodelinfo =
 +
        remodelinfo ..
 +
        " " ..
 +
          string.format("[[File:Item Icon Remodel Blueprint.png|25px|Blueprint|link=Blueprints]] %d", ship.remodelbp)
 
     end
 
     end
 
+
     if ship.remodelcatapult then
    local remodelinfo = ''
+
      remodelinfo =
     if shipInfo.remodelreq and shipInfo.remodelreq ~= '' then
+
         remodelinfo ..
        remodelinfo = string.format('[[File:IcoSteel.png|18px|Steel]] %d [[File:IcoAmmo.png|18px|Ammo]] %d', shipInfo.remodelreq[1], shipInfo.remodelreq[2])
+
         " " ..
         if shipInfo.remodelbp then
+
           string.format(
          remodelinfo = remodelinfo .. ' ' .. string.format('[[File:Item Icon Remodel Blueprint.png|25px|Blueprint|link=Blueprints]] %d', shipInfo.remodelbp)
+
            "[[File:Item Icon Prototype Flight Deck Catapult.png|25px|Prototype Flight Deck Catapult|link=Prototype Flight Deck Catapult]] %d",
         end
+
            ship.remodelcatapult
        if shipInfo.remodelcatapult then
+
           )
           remodelinfo = remodelinfo .. ' ' .. string.format('[[File:Item Icon Prototype Flight Deck Catapult.png|25px|Prototype Flight Deck Catapult|link=Prototype Flight Deck Catapult]] %d', shipInfo.remodelcatapult)
 
        end
 
        if shipInfo.remodelar then
 
          remodelinfo = remodelinfo .. ' ' .. string.format('[[File:Item Icon Action Report.png|25px|Action Report|link=Action Report]] %d', shipInfo.remodelar)
 
        end
 
        if shipInfo.remodeldevmat or shipInfo.remodelconmat or shipInfo.remodelgunmat or shipInfo.remodelairmat then
 
          remodelinfo = remodelinfo .. '<br>'
 
        end
 
        if shipInfo.remodeldevmat then
 
           remodelinfo = remodelinfo .. ' ' .. string.format('[[File:IcoDevmat.png|18px|Development Material]] %d', shipInfo.remodeldevmat)
 
        end
 
        if shipInfo.remodelconmat then
 
          remodelinfo = remodelinfo .. ' ' .. string.format('[[File:IcoConmat.png|18px|Construction Material]] %d', shipInfo.remodelconmat)
 
        end
 
        if shipInfo.remodelgunmat then
 
          remodelinfo = remodelinfo .. ' ' .. string.format('[[File:Item Icon New Model Gun Mount Improvement Material.png|18px|New Model Gun Mount Improvement Material|link=New Model Gun Development Material]] %d', shipInfo.remodelgunmat)
 
        end
 
        if shipInfo.remodelairmat then
 
          remodelinfo = remodelinfo .. ' ' .. string.format('[[File:Item Icon New Model Aerial Armament Material.png|18px|New Model Aerial Armament Material|link=New Model Aviation Development Material]] %d', shipInfo.remodelairmat)
 
        end
 
        if shipInfo.remodelarmmat then
 
          remodelinfo = remodelinfo .. ' ' .. string.format('[[File:Item Icon New Model Armament Material.png|18px|New Model Armament Material|link=New Model Armament Material]] %d', shipInfo.remodelarmmat)
 
        end
 
        if shipInfo.remodelboiler then
 
          remodelinfo = remodelinfo .. ' ' .. string.format('[[File:Item Icon New Model High Temperature High Pressure Boiler.png|18px|New Model High Temperature High Pressure Boiler|link=New Model High Temperature High Pressure Boiler]] %d', shipInfo.remodelboiler)
 
        end
 
 
     end
 
     end
      
+
     if ship.remodelar then
    -- Construction & Remodel
+
      remodelinfo =
    local row11 = ''
+
         remodelinfo ..
    if constrheader == 'Build Time' then
+
        " " ..
         row11 = '<tr>' .. RscHeader .. constrheader .. '</th>' .. RscData .. constrdata .. '</td><td colspan="2">&nbsp;</td></tr>'
+
          string.format("[[File:Item Icon Action Report.png|25px|Action Report|link=Action Report]] %d", ship.remodelar)
    else
 
        row11 = '<tr>' .. RscHeader .. constrheader .. '</th>' .. RscData .. constrdata .. '</td>' .. RscHeader .. 'Remodel Req</th>' .. RscData .. remodelinfo .. '</td></tr>'
 
 
     end
 
     end
 
+
     if ship.remodeldevmat or ship.remodelconmat or ship.remodelgunmat or ship.remodelairmat then
     -- Consumption
+
      remodelinfo = remodelinfo .. "<br>"
    local consfuel = '[[File:IcoFuel.png|18px|Fuel]] ' .. shipInfo["consumption"][1]
 
    local consammo = '[[File:IcoAmmo.png|18px|Ammo]] ' .. shipInfo["consumption"][2]
 
 
 
    local row12 = '<tr>' .. RscHeader .. 'Consumption</th>' .. RscData .. consfuel .. ' ' .. consammo .. '</td>'
 
 
 
    -- Scrap Info
 
    local scrapfuel = '[[File:IcoFuel.png|18px|Fuel]] ' .. shipInfo["dismantle"][1]
 
    local scrapammo = '[[File:IcoAmmo.png|18px|Ammo]] ' .. shipInfo["dismantle"][2]
 
    local scrapsteel = '[[File:IcoSteel.png|18px|Steel]] ' .. shipInfo["dismantle"][3]
 
    local scrapbauxite = '[[File:IcoBauxite.png|18px|Bauxite]] ' .. shipInfo["dismantle"][4]
 
    local scrapinfo = scrapfuel .. ' ' .. scrapammo .. ' ' .. scrapsteel .. ' ' .. scrapbauxite
 
    local row12 = row12 .. RscHeader .. 'Dismantle</th>' .. RscData .. scrapinfo .. '</td></tr>'
 
 
 
    -- Modernization
 
    local modFP = '[[File:IcoAtkRemodel.png|25px|Firepower]] ' .. shipInfo["modernization"][1]
 
    local modTorp = '[[File:IcoTorpedoRemodel.png|25px|Torpedo]] ' .. shipInfo["modernization"][2]
 
    local modAA = '[[File:IcoAARemodel.png|25px|Anti-Air]] ' .. shipInfo["modernization"][3]
 
    local modArmor = '[[File:IcoArmorRemodel.png|25px|Armor]] ' .. shipInfo["modernization"][4]
 
    local modLuck = ''
 
    if shipInfo["modernization"][5] ~= nil and shipInfo["modernization"][5] ~= "" then
 
        -- modLuck = '[[File:IcoLuck|18px|Luck]] ' .. shipInfo["modernization"][5]
 
        modLuck = '[[File:IcoLuckRemodel.png|25px|Luck]] ' .. shipInfo["modernization"][5] -- Just a placeholder
 
 
     end
 
     end
 
+
     if ship.remodeldevmat then
     local modInfo = modFP .. ' ' .. modTorp .. ' ' .. modAA .. ' ' .. modArmor
+
      remodelinfo =
    if modLuck ~= '' then
+
         remodelinfo .. " " .. string.format("[[File:IcoDevmat.png|18px|Development Material]] %d", ship.remodeldevmat)
         modInfo = modInfo .. ' ' .. modLuck
 
 
     end
 
     end
     local row13 = '<tr>' .. RscHeader .. 'Modernization</th>' .. RscData2 .. modInfo .. '</td></tr>'
+
     if ship.remodelconmat then
    -- return '<table style="width: 100%">' .. row13 .. row11 .. row12 .. '</table>'
+
      remodelinfo =
    return row13 .. row11 .. row12
+
        remodelinfo .. " " .. string.format("[[File:IcoConmat.png|18px|Construction Material]] %d", ship.remodelconmat)
end
 
 
 
function shipmodule.getArtVoice(frame)
 
    local shipNum = shipmodule.getIDNum(frame)
 
    local shipInfo = assert(shipmodule.data[shipNum], "KanMusu ID " .. shipNum .. " doesn't have a database entry")
 
    local RscHeader = '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #3baef5; color: #ffffff; padding-left: 5px; padding-right: 5px; text-align: right;">'
 
    local RscData = '<td style="width: 25%; white-space: nowrap; text-align: center;">'
 
    local illustrator = ''
 
    local voiceactor = ''
 
    if shipmodule.data[shipNum]["artist"] ~= "Unknown" and shipmodule.data[shipNum]["artist"] ~= "" then
 
        illustrator = '[[:Category:' .. shipmodule.data[shipNum]["artist"] .. '|' .. shipmodule.data[shipNum]["artist"] .. ']]'
 
    else
 
        illustrator = 'Unknown'
 
 
     end
 
     end
     art = RscHeader .. 'Artist</th>' .. RscData .. illustrator .. '</td>'
+
     if ship.remodelgunmat then
    if shipmodule.data[shipNum]["seiyuu"] ~= "Unknown" and shipmodule.data[shipNum]["seiyuu"] ~= "" then
+
      remodelinfo =
         voiceactor = '[[:Category:' .. shipmodule.data[shipNum]["seiyuu"] .. '|' .. shipmodule.data[shipNum]["seiyuu"] .. ']]'
+
         remodelinfo ..
    else
+
        " " ..
        voiceactor = 'Unknown'
+
          string.format(
 +
            "[[File:Item Icon New Model Gun Mount Improvement Material.png|18px|New Model Gun Mount Improvement Material|link=New Model Gun Development Material]] %d",
 +
            ship.remodelgunmat
 +
          )
 
     end
 
     end
     voice = RscHeader .. 'Seiyuu</th>' .. RscData .. voiceactor .. '</td>'
+
     if ship.remodelairmat then
    --local row14 = '<table style="width: 100%">' .. art .. voice .. '</table>'
+
      remodelinfo =
    return art .. voice
+
        remodelinfo ..
end
+
        " " ..
 
+
          string.format(
function shipmodule.createCategories(frame)
+
            "[[File:Item Icon New Model Aerial Armament Material.png|18px|New Model Aerial Armament Material|link=New Model Aviation Development Material]] %d",
local shipNum = shipmodule.getIDNum(frame)
+
            ship.remodelairmat
+
          )
    local shipInfo = assert(shipmodule.data[shipNum], "KanMusu ID " .. shipNum .. " doesn't have a database entry")
 
 
 
local cat = '[[Category:Ships]]'
 
cat = cat .. '[[Category:' .. shipmodule.data[shipNum]["class"] .. ' Class]][[Category:' .. shipmodule.data[shipNum]["type"] .. 's]]'
 
if shipmodule.data[shipNum]["artist"] ~= "Unknown" and shipmodule.data[shipNum]["artist"] ~= "" then
 
      cat = cat .. '[[Category:' .. shipmodule.data[shipNum]["artist"] .. ']]'
 
 
     end
 
     end
     if shipmodule.data[shipNum]["seiyuu"] ~= "Unknown" and shipmodule.data[shipNum]["seiyuu"] ~= "" then
+
     if ship.remodelarmmat then
        cat = cat .. '[[Category:' .. shipmodule.data[shipNum]["seiyuu"] .. ']]'
+
      remodelinfo =
 +
        remodelinfo ..
 +
        " " ..
 +
          string.format(
 +
            "[[File:Item Icon New Model Armament Material.png|18px|New Model Armament Material|link=New Model Armament Material]] %d",
 +
            ship.remodelarmmat
 +
          )
 
     end
 
     end
return cat
+
     if ship.remodelboiler then
end
+
      remodelinfo =
 
+
        remodelinfo ..
function shipmodule.KanmusuList(frame)
+
        " " ..
     local shipType = frame.args[1]
+
          string.format(
    local shipListTable = '<table class="wikitable filterable sortable" style="width: 100%; min-width: 800px;"><tr>'
+
            "[[File:Item Icon New Model High Temperature High Pressure Boiler.png|18px|New Model High Temperature High Pressure Boiler|link=New Model High Temperature High Pressure Boiler]] %d",
    shipListTable = shipListTable .. '<th style="text-align: center; background-color: SpringGreen;" class="unfilterable" data-sort-type="number">ID</th>'
+
             ship.remodelboiler
    shipListTable = shipListTable .. '<th style="text-align: center; background-color: SpringGreen;" class="unfilterable unsortable">Name</th>'
+
          )
    shipListTable = shipListTable .. '<th style="text-align: center; background-color: SpringGreen;" class="unfilterable unsortable">Class</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; background-color: SpringGreen;" class="unsortable">Type</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: LightCoral;" class="unfilterable">[[File:IcoAtk.png|Firepower]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: LightSkyBlue;" class="unfilterable">[[File:IcoTorpedo.png|Torpedo]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: SandyBrown;" class="unfilterable">[[File:IcoAA.png|Anti-Air]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: Seashell;" class="unfilterable">[[File:IcoASW.png|Anti-Submarine Warfare]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: Aquamarine;" class="unfilterable">[[File:IcoLOS.png|Line of Sight]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: PaleGreen;" class="unfilterable">[[File:IcoLuck.png|Luck]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: Pink;" class="unfilterable">[[File:IcoHP.png|HP]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: Yellow;" class="unfilterable">[[File:IcoArmor.png|Armor]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: Violet;" class="unfilterable">[[File:IcoEvasion.png|Evasion]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: Silver;" class="unfilterable">[[File:IcoAircraft.png|Aircraft]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; vertical-align: middle; background-color: Aqua;" class="unsortable">[[File:IcoSpeed.png|Speed|link=]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; background-color: SpringGreen;" class="unsortable">[[File:IcoRange.png|Range|link=]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; background-color: SpringGreen;" class="unfilterable">[[File:IcoFuel.png|Fuel Consumption]]</th>'
 
    shipListTable = shipListTable .. '<th style="text-align: center; background-color: SpringGreen;" class="unfilterable">[[File:IcoAmmo.png|Ammo Consumption]]</th></tr>'
 
    local IDList = shipdb.getSortedIDList()
 
    for num, id in pairs(IDList) do
 
        if shipType ~= nil then
 
             if shipType == shipmodule.data[id]["type"] then
 
                shipListTable = shipListTable .. shipmodule.KanmusuListEntry(id, frame.args[2] ~= nil)
 
            end
 
        else
 
            shipListTable = shipListTable .. shipmodule.KanmusuListEntry(id, frame.args[2] ~= nil)
 
        end
 
 
     end
 
     end
     shipListTable = shipListTable .. '</table>'
+
  end
     return shipListTable
+
  -- Construction & Remodel
 +
  local row11 = ""
 +
  if constrheader == "Build Time" then
 +
     row11 =
 +
      "<tr>" .. RscHeader .. constrheader .. "</th>" .. RscData .. constrdata .. '</td><td colspan="2">&nbsp;</td></tr>'
 +
  else
 +
    row11 =
 +
      "<tr>" ..
 +
      RscHeader ..
 +
        constrheader ..
 +
          "</th>" ..
 +
            RscData ..
 +
              constrdata .. "</td>" .. RscHeader .. "Remodel Req</th>" .. RscData .. remodelinfo .. "</td></tr>"
 +
  end
 +
  -- Consumption
 +
  local consfuel = "[[File:IcoFuel.png|18px|Fuel]] " .. ship["consumption"][1]
 +
  local consammo = "[[File:IcoAmmo.png|18px|Ammo]] " .. ship["consumption"][2]
 +
  local row12 = "<tr>" .. RscHeader .. "Consumption</th>" .. RscData .. consfuel .. " " .. consammo .. "</td>"
 +
  -- Scrap Info
 +
  local scrapfuel = "[[File:IcoFuel.png|18px|Fuel]] " .. ship["dismantle"][1]
 +
  local scrapammo = "[[File:IcoAmmo.png|18px|Ammo]] " .. ship["dismantle"][2]
 +
  local scrapsteel = "[[File:IcoSteel.png|18px|Steel]] " .. ship["dismantle"][3]
 +
  local scrapbauxite = "[[File:IcoBauxite.png|18px|Bauxite]] " .. ship["dismantle"][4]
 +
  local scrapinfo = scrapfuel .. " " .. scrapammo .. " " .. scrapsteel .. " " .. scrapbauxite
 +
  local row12 = row12 .. RscHeader .. "Dismantle</th>" .. RscData .. scrapinfo .. "</td></tr>"
 +
  -- Modernization
 +
  local modFP = "[[File:IcoAtkRemodel.png|25px|Firepower]] " .. ship["modernization"][1]
 +
  local modTorp = "[[File:IcoTorpedoRemodel.png|25px|Torpedo]] " .. ship["modernization"][2]
 +
  local modAA = "[[File:IcoAARemodel.png|25px|Anti-Air]] " .. ship["modernization"][3]
 +
  local modArmor = "[[File:IcoArmorRemodel.png|25px|Armor]] " .. ship["modernization"][4]
 +
  local modLuck = ""
 +
  if ship["modernization"][5] ~= nil and ship["modernization"][5] ~= "" then
 +
    modLuck = "[[File:IcoLuckRemodel.png|25px|Luck]] " .. ship["modernization"][5]
 +
  end
 +
  local modInfo = modFP .. " " .. modTorp .. " " .. modAA .. " " .. modArmor
 +
  if modLuck ~= "" then
 +
     modInfo = modInfo .. " " .. modLuck
 +
  end
 +
  local row13 = "<tr>" .. RscHeader .. "Modernization</th>" .. RscData2 .. modInfo .. "</td></tr>"
 +
  return row13 .. row11 .. row12
 
end
 
end
  
function shipmodule.KanmusuListEntry(id, printMax) -- Kanmusu List Table
+
local function renderArtists(ship)
    local strings = '<tr>'
+
  local RscHeader =
    local aircraftTotal = 0
+
    '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #3baef5; color: #ffffff; padding-left: 5px; padding-right: 5px; text-align: right;">'
    if shipmodule.data[id]["aircraft"] ~= "" then
+
  local RscData = '<td style="width: 25%; white-space: nowrap; text-align: center;">'
    local aircraftslot = {0, 0, 0, 0}
+
  local illustrator =
        for i = 1, 4, 1 do
+
    ship["artist"] ~= "Unknown" and ship["artist"] ~= "" and
            if shipmodule.data[id]["aircraft"][i] ~= nil then
+
     ("[[:Category:" .. ship["artist"] .. "|" .. ship["artist"] .. "]]") or
                aircraftslot[i] = shipmodule.data[id]["aircraft"][i]
+
     "Unknown"
            else
+
  local voiceactor =
                aircraftslot[i] = 0
+
     ship["seiyuu"] ~= "Unknown" and ship["seiyuu"] ~= "" and
            end
+
     ("[[:Category:" .. ship["seiyuu"] .. "|" .. ship["seiyuu"] .. "]]") or
        end
+
     "Unknown"
        aircraftTotal = aircraftslot[1] + aircraftslot[2] + aircraftslot[3] + aircraftslot[4]
+
  return RscHeader ..
    else
+
     "Artist</th>" .. RscData .. illustrator .. "</td>" .. RscHeader .. "Seiyuu</th>" .. RscData .. voiceactor .. "</td>"
        aircraftTotal = 0
 
    end
 
   
 
    --finding name of wiki page of ship
 
    shipname = shipmodule.data[id]["name"][3]
 
    pagename = shipname
 
    if string.sub(id,1,-2) == "Mist" then  -- fleet of fog check
 
    if string.sub(id, -1) == '1' then
 
    pagename = 'Iona_(fog)'
 
    elseif string.sub(id, -1) == '2' then
 
    pagename = 'Takao_(fog)'
 
    elseif string.sub(id, -1) == '3' then
 
    pagename = 'Haruna_(fog)'
 
else
 
pagename = 'Fleet of Fog'
 
end
 
else
 
shipbasename = mw.text.split(shipname, '%s')[1]
 
--Chitose/Chiyoda-Kou check; submarines should be unaffected
 
if mw.text.split(shipbasename, '%p')[2] ~= nil and mw.text.split(shipbasename, '%p')[2] == "Kou" then
 
shipbasename = mw.text.split(shipbasename, '%p')[1]
 
end
 
--Prinz/Graf/Teste check (for ship names that are 2 or more words)
 
if mw.text.split(shipname, '%s')[2] ~= nil and not (mw.text.split(shipname, '%s')[2] == "Kai" or
 
mw.text.split(shipname, '%s')[2] == "A" or mw.text.split(shipname, '%s')[2] == "zwei" or
 
mw.text.split(shipname, '%s')[2] == "drei" or mw.text.split(shipname, '%s')[2] == "Due" or
 
mw.text.split(shipname, '%s')[2] == "Dva") then
 
shipbasename = shipbasename .. ' ' .. mw.text.split(shipname, '%s')[2]
 
end
 
pagename = shipbasename
 
end
 
 
 
    statLevel = 1 --base stat
 
    if printMax then
 
statLevel = 2 --max stat
 
end
 
 
    strings = strings .. '<td style="text-align: center;">' .. id .. '</td>'
 
    strings = strings .. '<td style="text-align: center;">[[' .. pagename .. '|' .. shipname ..']]</td>'
 
    strings = strings .. '<td style="text-align: center;">' .. shipmodule.data[id]["class"] .. '</td>'
 
    strings = strings .. '<td style="text-align: center;">' .. shipmodule.data[id]["type"] .. '</td>'
 
    strings = strings .. '<td style="text-align: center; background-color: #f0bbbb;">' .. shipmodule.data[id]["fp"][statLevel] .. '</td>'
 
     if shipmodule.data[id]["torpedo"] == 0 then
 
        strings = strings .. '<td style="text-align: center; background-color: #99eefa;">' .. shipmodule.data[id]["torpedo"] .. '</td>'
 
    else
 
        strings = strings .. '<td style="text-align: center; background-color: #99eefa;">' .. shipmodule.data[id]["torpedo"][statLevel] .. '</td>'
 
    end
 
    if shipmodule.data[id]["aa"] == 0 then
 
        strings = strings .. '<td style="text-align: center; background-color: #faccaa;">' .. shipmodule.data[id]["aa"] .. '</td>'
 
     else
 
        strings = strings .. '<td style="text-align: center; background-color: #faccaa;">' .. shipmodule.data[id]["aa"][statLevel] .. '</td>'
 
    end
 
     if shipmodule.data[id]["asw"] == 0 then
 
        strings = strings .. '<td style="text-align: center; background-color: #fff5ee;">' .. shipmodule.data[id]["asw"] .. '</td>'
 
    else
 
        strings = strings .. '<td style="text-align: center; background-color: #fff5ee;">' .. shipmodule.data[id]["asw"][statLevel] .. '</td>'
 
     end
 
    strings = strings .. '<td style="text-align: center; background-color: #afffee;">' .. shipmodule.data[id]["los"][statLevel] .. '</td>'
 
    strings = strings .. '<td style="text-align: center; background-color: #cbfbcb;">' .. shipmodule.data[id]["luck"][statLevel] .. '</td>'
 
    strings = strings .. '<td style="text-align: center; background-color: #ffe0eb;">' .. shipmodule.data[id]["hp"][statLevel] .. '</td>'
 
     strings = strings .. '<td style="text-align: center; background-color: #ffffaa;">' .. shipmodule.data[id]["armor"][statLevel] .. '</td>'
 
     strings = strings .. '<td style="text-align: center; background-color: #eeccee;">' .. shipmodule.data[id]["evasion"][statLevel] .. '</td>'
 
    strings = strings .. '<td style="text-align: center; background-color: #d9d9d9;">' .. aircraftTotal .. '</td>'
 
    strings = strings .. '<td style="text-align: center; background-color: #aaffff;">' .. shipmodule.data[id]["spd"] .. '</td>'
 
    strings = strings .. '<td style="text-align: center;">' .. shipmodule.data[id]["range"] .. '</td>'
 
    strings = strings .. '<td style="text-align: center;">' .. shipmodule.data[id]["consumption"][1] .. '</td>'
 
    strings = strings .. '<td style="text-align: center;">' .. shipmodule.data[id]["consumption"][2] .. '</td></tr>'
 
    return strings
 
 
end
 
end
  
local function numToID(num)
+
local function renderCategories(ship)
return num < 10 and "00" .. num or num < 100 and "0" .. num or tostring(num)
+
  local categories = "[[Category:Ships]][[Category:" .. ship["class"] .. " Class]][[Category:" .. ship["type"] .. "s]]"
 +
  if ship["artist"] ~= "Unknown" and ship["artist"] ~= "" then
 +
    categories = categories .. "[[Category:" .. ship["artist"] .. "]]"
 +
  end
 +
  if ship["seiyuu"] ~= "Unknown" and ship["seiyuu"] ~= "" then
 +
    categories = categories .. "[[Category:" .. ship["seiyuu"] .. "]]"
 +
  end
 +
  return categories
 
end
 
end
  
function shipmodule.CardList()
+
local function render(frame)
firstID = 1
+
  local ShipData = mw.loadData("Module:Data/Ship")
maxID = -1
+
  local shipNum = frame.args[1]
for KanMusuID, KanMusuData in pairs(shipmodule.data) do
+
  local ship = ShipData[shipNum]
if tonumber(KanMusuID) ~= nil and tonumber(KanMusuID) > maxID then
+
  return '<div style="display:inline-block;vertical-align:top"><table style="{{border-radius|10px 10px 10px 10px}} border:1px solid #aaaaaa;min-width:495px"><tr><td>' ..
maxID = tonumber(KanMusuID)
+
    renderStats(ship, shipNum) ..
end
+
      "</td></tr><tr><td>" ..
end
+
        renderEquipment(ship) ..
IDRange = math.ceil(maxID / 10) * 10
+
          '<table style="width:100%">' ..
wikipage = ""
+
            renderModernization(ship) ..
while firstID < IDRange do
+
              renderArtists(ship) .. "</table></td></tr></table></div>" .. renderCategories(ship)
wikipage = wikipage .. "<h2>No. " .. tostring(firstID) .. "-" .. tostring(firstID+9) .. "</h2>"
 
for i = 0, 9 do
 
x = firstID + i
 
shipID = numToID(x)
 
if not shipmodule.data[shipID] then
 
wikipage = wikipage .. "[[File:blank.png|150px]]"
 
else
 
local shipName = shipmodule.data[shipID].name[3]
 
wikipage = wikipage .. "[[File:Ship Card " .. shipName .. ".png|150px|link=" .. shipdb.getWikiPage(shipID) .. "]]"
 
end
 
if x % 5 == 0 then
 
wikipage = wikipage .. "<br>"
 
end
 
end
 
wikipage = wikipage .. "<br>"
 
firstID = firstID + 10
 
end
 
return wikipage
 
 
end
 
end
  
return shipmodule
+
return {KanmusuInfo = render}

Revision as of 14:46, 10 September 2022

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

local U = require("Module:Core")

-- Some formatting

local function formatBuildtime(minutes)
  return U.format {"${hours}:${minutes:2}", hours = math.floor(minutes / 60), minutes = minutes % 60}
end

local function formatTooltip(content, title)
  return tostring(mw.html.create("span"):attr("title", title):addClass("explain"):wikitext(content))
end

-- Some calculations

local function getTotalAircraft(ship)
  local total = 0
  if ship.aircraft ~= "" then
    for i, _ in pairs(ship.aircraft) do
      if ship.aircraft[i] == nil or ship.aircraft[i] == "" then
        total = total + 0
      else
        total = total + ship.aircraft[i]
      end
    end
  end
  return total
end

local function getMarriedHp(hp, maxHp)
  return math.min(maxHp, hp + ({4, 4, 4, 5, 6, 7, 7, 8, 8, 9})[math.floor(hp / 10) + 1])
end

-- The ship infobox stuff...

local function renderStats(ship, shipNum)
  local shipName = ship.name[3]
  local CardImg = '<div class="top-image">[[File:Ship Card ' .. shipName .. ".png|218x300px|link=]]</div>"
  local CardDmgImg = '<div class="bottom-image">[[File:Ship Card ' .. shipName .. " Damaged.png|218x300px|link=]]</div>"
  local BannerImg = '<div class="top-image">[[File:Ship Banner ' .. shipName .. ".png|link=]]</div>"
  local BannerDmgImg = '<div class="bottom-image">[[File:Ship Banner ' .. shipName .. " Damaged.png|link=]]</div>"
  local Cards =
    '<td rowspan="10" class="double-image" style="width:218px;height:300px">' .. CardImg .. CardDmgImg .. "</td>"
  local Banners =
    '<td colspan="3" class="double-image" style="width:240px;height:60px">' .. BannerImg .. BannerDmgImg .. "</td>"
  local sortNo = ship.sortno or U.split(shipNum, "-")[1] or "?"
  local row1 = "<tr>" .. Cards .. '<th style="text-align: center;">' .. sortNo .. "</th>" .. Banners .. "</tr>"
  -- Formatting Japanese
  local kanji, form
  local formNum = mw.ustring.find(ship["name"][1], "[乙改甲航]")
  if formNum == nil then
    if mw.ustring.find(ship["name"][1], "%szwei") ~= nil then
      formNum = mw.ustring.find(ship["name"][1], "%szwei")
      kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
      form = "&#32;zwei"
    elseif mw.ustring.find(ship["name"][1], "%sdrei") ~= nil then
      formNum = mw.ustring.find(ship["name"][1], "%sdrei")
      kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
      form = "&#32;drei"
    elseif mw.ustring.find(ship["name"][1], "%sdue") ~= nil then
      formNum = mw.ustring.find(ship["name"][1], "%sdue")
      kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
      form = "&#32;due"
    elseif mw.ustring.find(ship["name"][1], "%sдва") ~= nil then
      formNum = mw.ustring.find(ship["name"][1], "%sдва")
      kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
      form = "&#32;два"
    elseif mw.ustring.find(ship["name"][1], "%sMk.II") ~= nil then
      if mw.ustring.find(ship["name"][1], "%sMk.II Mod.2") ~= nil then
        formNum = mw.ustring.find(ship["name"][1], "%sMk.II Mod.2")
        kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
        form = "&#32;Mk.II Mod.2"
      else
        formNum = mw.ustring.find(ship["name"][1], "%sMk.II")
        kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
        form = "&#32;Mk.II"
      end
    elseif mw.ustring.find(ship["name"][1], "%sреволюция") ~= nil then -- Gangut "Kai" exception
      kanji = mw.text.split(ship["name"][1], "%s")[1] .. "<br/>" .. mw.text.split(ship["name"][1], "%s")[2]
      form = ""
    else
      kanji = ship["name"][1]
      form = ""
    end
  else
    kanji = mw.ustring.sub(ship["name"][1], 1, formNum - 1)
    form = mw.ustring.sub(ship["name"][1], formNum, -1)
  end
  local JaName = ""
  if
    shipNum == "147" or shipNum == "311" or shipNum == "312" or shipNum == "313" or shipNum == "313a" or
      shipNum == "316"
   then --Russian ship markup
    JaName =
      '<ruby lang="ru"><rb>' ..
      kanji ..
        '<span lang="ru">' ..
          form .. "</span>" .. '</rb><rp> (</rp><rt lang="ja">' .. ship["name"][2] .. "</rt><rp>) </rp></ruby>"
  else
    if ship.name[2] then
      JaName =
        '<ruby lang="ja"><rb>' ..
        kanji .. "<span>" .. form .. "</span>" .. "</rb><rp> (</rp><rt>" .. ship.name[2] .. "</rt><rp>) </rp></ruby>"
    else
      JaName = '<ruby lang="ja"><rb>' .. kanji .. "<span>" .. form .. "</span>" .. "</rb></ruby>"
    end
  end
  -- Summary of basic ship info
  local isCVE =
    ship.type == "Light Carrier" and type(ship.asw) == "table" and type(ship.asw[1]) == "number" and ship.asw[1] > 0
  local shipType =
    isCVE and string.format('<span class="explain" title="CVE">%s[[Category:Escort Carriers]]</span>', ship.type) or
    ship.type
  local row2 = '<tr><th colspan="2">' .. JaName .. '</th><th colspan="2">' .. ship.name[3] .. "</th></tr>"
  local row3 = '<tr><td colspan="4" style="text-align: center;">' .. ship.class .. " Class " .. shipType .. "</td></tr>"
  local row4 =
    '<tr><td colspan="4"><hr style="border: 0; height: 1px; background-image: linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));" /></td></tr>'
  -- Ship stats table
  local statLabel =
    '<th style="width: 65px; {{border-radius|12px 4px 4px 12px}} padding-left: 5px; padding-right: 5px; background-color: #eae1d1; color: #a3965c; text-align: right; vertical-align: baseline;">'
  local statBox =
    '<td style="{{border-radius|4px 12px 12px 4px}} padding-left: 5px; padding-right: 5px; border: 1px solid #a3965c; text-align: left; vertical-align: baseline;">'
  local hp = ship["hp"][1]
  local maxHp = ship["hp"][2]
  local HPinfo
  if maxHp then
    local marriedHp = getMarriedHp(hp, maxHp)
    local maxModHp = math.min(hp + 2, maxHp)
    local maxModMarriedHp = math.min(marriedHp + 2, maxHp)
    local hpSpan1 = hp == maxModHp and hp or formatTooltip(hp, string.format("%d with HP modernization", maxModHp))
    local hpSpan2 =
      formatTooltip(
      marriedHp,
      marriedHp == maxModMarriedHp and "Married" or string.format("Married, %d with HP modernization", maxModMarriedHp)
    )
    HPinfo = statLabel .. "HP [[File:IcoHP.png|HP]]</th>" .. statBox .. hpSpan1 .. "→" .. hpSpan2 .. "</td>"
  else
    HPinfo = statLabel .. "HP [[File:IcoHP.png|HP]]</th>" .. statBox .. hp .. "</td>"
  end
  local FPinfo =
    statLabel .. "FP [[File:IcoAtk.png|Firepower]]</th>" .. statBox .. ship["fp"][1] .. "→" .. ship["fp"][2] .. "</td>"
  local row5 = "<tr>" .. HPinfo .. FPinfo .. "</tr>"
  -- Armor & Torpedo
  local Armorinfo =
    statLabel ..
    "ARM [[File:IcoArmor.png|Armor]]</th>" .. statBox .. ship["armor"][1] .. "→" .. ship["armor"][2] .. "</td>"
  local Torpedoinfo = statLabel .. "TORP [[File:IcoTorpedo.png|Torpedo]]</th>" .. statBox
  if ship["torpedo"] == 0 then
    Torpedoinfo = Torpedoinfo .. ship["torpedo"]
  else
    Torpedoinfo = Torpedoinfo .. ship["torpedo"][1] .. "→" .. ship["torpedo"][2]
  end
  local row6 = "<tr>" .. Armorinfo .. Torpedoinfo .. "</tr>"
  -- Evasion & AA
  local Evasioninfo =
    statLabel ..
    "EVA [[File:IcoEvasion.png|Evasion]]</th>" .. statBox .. ship["evasion"][1] .. "→" .. ship["evasion"][2] .. "</td>"
  local AAinfo = statLabel .. "AA [[File:IcoAA.png|Anti-Air]]</th>" .. statBox
  if ship["aa"] == 0 then
    AAinfo = AAinfo .. ship["aa"]
  else
    AAinfo = AAinfo .. ship["aa"][1] .. "→" .. ship["aa"][2]
  end
  local row7 = "<tr>" .. Evasioninfo .. AAinfo .. "</tr>"
  -- Planes & ASW
  local aircraftTotal = getTotalAircraft(ship)
  local Planeinfo = statLabel .. "PLA [[File:IcoAircraft.png|Aircraft]]</th>" .. statBox .. aircraftTotal .. "</td>"
  local ASWinfo = statLabel .. "ASW [[File:IcoASW.png|Anti-Submarine Warfare]]</th>" .. statBox
  if ship["asw"] == 0 then
    ASWinfo = ASWinfo .. ship["asw"]
  else
    ASWinfo = ASWinfo .. ship["asw"][1] .. "→" .. ship["asw"][2]
  end
  local row8 = "<tr>" .. Planeinfo .. ASWinfo .. "</tr>"
  -- Speed & LOS
  local Speedinfo = statLabel .. "SPD [[File:IcoSpeed.png|Speed]]</th>" .. statBox .. ship["spd"] .. "</td>"
  local LOSinfo =
    statLabel ..
    "LOS [[File:IcoLOS.png|Line of Sight]]</th>" .. statBox .. ship["los"][1] .. "→" .. ship["los"][2] .. "</td>"
  local row9 = "<tr>" .. Speedinfo .. LOSinfo .. "</tr>"
  -- Range & Luck
  local Rangeinfo = statLabel .. "RGE [[File:IcoRange.png|Range]]</th>" .. statBox .. ship["range"] .. "</td>"
  local Luckinfo =
    statLabel .. "LUK [[File:IcoLuck.png|Luck]]</th>" .. statBox .. ship["luck"][1] .. "→" .. ship["luck"][2] .. "</td>"
  local row10 = "<tr>" .. Rangeinfo .. Luckinfo .. "</tr>"
  local StatTable =
    "<table>" .. row1 .. row2 .. row3 .. row4 .. row5 .. row6 .. row7 .. row8 .. row9 .. row10 .. "</table>"
  return StatTable
end

local function renderEquipment(ship)
  local equipHeader = ""
  local planeStyle = '<td style="width: 25%; white-space: nowrap; text-align: center; vertical-align: top;">'
  local equipStyle = ""
  if ship["aircraft"] ~= "" then
    local equipHeader1 =
      '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #efe6d7; color: #a3965c;">Aircraft</th>'
    local equipHeader2 =
      '<th style="width: 75%; white-space: nowrap; {{border-radius|4px 12px 12px 4px}} background-color: #efe6d7; color: #a3965c; vertical-align: baseline;">Equipment</th>'
    equipHeader = equipHeader1 .. equipHeader2
    equipStyle = '<td style="width: 75%; max-width: 375px; text-align: center; vertical-align: baseline;">'
  else
    equipHeader =
      '<th style="white-space: nowrap; {{border-radius|12px 12px 12px 12px}} background-color: #efe6d7; color: #a3965c; vertical-align: baseline;">Equipment</th>'
    equipStyle = '<td style="white-space: nowrap; text-align: center; vertical-align: baseline;">'
  end
  local numRows = math.max(4, U.isize(ship["equip"]))
  local equipTable = ""
  for i = 1, numRows, 1 do
    local equipRow = "<tr>"
    if ship["aircraft"] ~= "" then
      if ship["aircraft"][i] ~= nil then
        equipRow = equipRow .. planeStyle .. ship["aircraft"][i] .. "</td>" .. equipStyle
      else
        equipRow = equipRow .. planeStyle .. "</td>" .. equipStyle
      end
      if ship["equip"] ~= "" then
        if ship["equip"][i] == "" or ship["equip"][i] == "Unequipped" then
          equipRow = equipRow .. "-Unequipped-</td></tr>"
        elseif ship["equip"][i] == nil then
          equipRow = equipRow .. "''-Locked-''</td></tr>"
        else
          if string.find(ship["equip"][i], "%★") then
            local a, b = string.match(ship["equip"][i], "^(.+)★(.+)$")
            equipRow = equipRow .. "[[" .. a .. "|" .. a .. "★" .. b .. "]]</td></tr>"
          else
            equipRow = equipRow .. "[[" .. ship["equip"][i] .. "]]</td></tr>"
          end
        end
      else
        equipRow = equipRow .. "''-Locked-''</td></tr>"
      end
    else
      equipRow = equipRow .. equipStyle
      if ship["equip"] ~= "" then
        if ship["equip"][i] == "" or ship["equip"][i] == "Unequipped" then
          equipRow = equipRow .. "-Unequipped-</td></tr>"
        elseif ship["equip"][i] == nil then
          equipRow = equipRow .. "''Locked''</td></tr>"
        else
          if string.find(ship["equip"][i], "%★") then
            local a, b = string.match(ship["equip"][i], "^(.+)★(.+)$")
            equipRow = equipRow .. "[[" .. a .. "|" .. a .. "★" .. b .. "]]</td></tr>"
          else
            equipRow = equipRow .. "[[" .. ship["equip"][i] .. "]]</td></tr>"
          end
        end
      else
        equipRow = equipRow .. "''Locked''</td></tr>"
      end
    end
    equipTable = equipTable .. equipRow
  end
  return '<table style="width: 100%">' .. equipHeader .. equipTable .. "</table>"
end

local function renderModernization(ship)
  local RscHeader =
    '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #3baef5; color: #ffffff; padding-left: 5px; padding-right: 5px; text-align: right;">'
  local RscData = '<td style="width: 25%; white-space: nowrap; text-align: center;">'
  local RscData2 = '<td colspan="3" style="width: 75%; white-space: nowrap; text-align: center;">'
  -- Construction info
  local constrheader = ""
  local constrdata = ""
  if ship["remodellv"] ~= nil and ship["remodellv"] ~= "" then
    constrheader = "Remodel Level"
    constrdata = ship["remodellv"]
  else
    constrheader = '<span class="explain-dash" title="h:mm">Build Time</span>'
    constrdata =
      type(ship.buildtime) ~= "table" and "??" or
      string.format(
        "%s (%s)",
        formatBuildtime(ship.buildtime[1]),
        ship.buildtime[2] and ship.buildtime[3] and "Normal, LSC" or ship.buildtime[2] and "Normal" or
          ship.buildtime[3] and "LSC" or
          "Unbuildable"
      )
  end
  local remodelinfo = ""
  if ship.remodelreq and ship.remodelreq ~= "" then
    remodelinfo =
      string.format(
      "[[File:IcoSteel.png|18px|Steel]] %d [[File:IcoAmmo.png|18px|Ammo]] %d",
      ship.remodelreq[1],
      ship.remodelreq[2]
    )
    if ship.remodelbp then
      remodelinfo =
        remodelinfo ..
        " " ..
          string.format("[[File:Item Icon Remodel Blueprint.png|25px|Blueprint|link=Blueprints]] %d", ship.remodelbp)
    end
    if ship.remodelcatapult then
      remodelinfo =
        remodelinfo ..
        " " ..
          string.format(
            "[[File:Item Icon Prototype Flight Deck Catapult.png|25px|Prototype Flight Deck Catapult|link=Prototype Flight Deck Catapult]] %d",
            ship.remodelcatapult
          )
    end
    if ship.remodelar then
      remodelinfo =
        remodelinfo ..
        " " ..
          string.format("[[File:Item Icon Action Report.png|25px|Action Report|link=Action Report]] %d", ship.remodelar)
    end
    if ship.remodeldevmat or ship.remodelconmat or ship.remodelgunmat or ship.remodelairmat then
      remodelinfo = remodelinfo .. "<br>"
    end
    if ship.remodeldevmat then
      remodelinfo =
        remodelinfo .. " " .. string.format("[[File:IcoDevmat.png|18px|Development Material]] %d", ship.remodeldevmat)
    end
    if ship.remodelconmat then
      remodelinfo =
        remodelinfo .. " " .. string.format("[[File:IcoConmat.png|18px|Construction Material]] %d", ship.remodelconmat)
    end
    if ship.remodelgunmat then
      remodelinfo =
        remodelinfo ..
        " " ..
          string.format(
            "[[File:Item Icon New Model Gun Mount Improvement Material.png|18px|New Model Gun Mount Improvement Material|link=New Model Gun Development Material]] %d",
            ship.remodelgunmat
          )
    end
    if ship.remodelairmat then
      remodelinfo =
        remodelinfo ..
        " " ..
          string.format(
            "[[File:Item Icon New Model Aerial Armament Material.png|18px|New Model Aerial Armament Material|link=New Model Aviation Development Material]] %d",
            ship.remodelairmat
          )
    end
    if ship.remodelarmmat then
      remodelinfo =
        remodelinfo ..
        " " ..
          string.format(
            "[[File:Item Icon New Model Armament Material.png|18px|New Model Armament Material|link=New Model Armament Material]] %d",
            ship.remodelarmmat
          )
    end
    if ship.remodelboiler then
      remodelinfo =
        remodelinfo ..
        " " ..
          string.format(
            "[[File:Item Icon New Model High Temperature High Pressure Boiler.png|18px|New Model High Temperature High Pressure Boiler|link=New Model High Temperature High Pressure Boiler]] %d",
            ship.remodelboiler
          )
    end
  end
  -- Construction & Remodel
  local row11 = ""
  if constrheader == "Build Time" then
    row11 =
      "<tr>" .. RscHeader .. constrheader .. "</th>" .. RscData .. constrdata .. '</td><td colspan="2">&nbsp;</td></tr>'
  else
    row11 =
      "<tr>" ..
      RscHeader ..
        constrheader ..
          "</th>" ..
            RscData ..
              constrdata .. "</td>" .. RscHeader .. "Remodel Req</th>" .. RscData .. remodelinfo .. "</td></tr>"
  end
  -- Consumption
  local consfuel = "[[File:IcoFuel.png|18px|Fuel]] " .. ship["consumption"][1]
  local consammo = "[[File:IcoAmmo.png|18px|Ammo]] " .. ship["consumption"][2]
  local row12 = "<tr>" .. RscHeader .. "Consumption</th>" .. RscData .. consfuel .. " " .. consammo .. "</td>"
  -- Scrap Info
  local scrapfuel = "[[File:IcoFuel.png|18px|Fuel]] " .. ship["dismantle"][1]
  local scrapammo = "[[File:IcoAmmo.png|18px|Ammo]] " .. ship["dismantle"][2]
  local scrapsteel = "[[File:IcoSteel.png|18px|Steel]] " .. ship["dismantle"][3]
  local scrapbauxite = "[[File:IcoBauxite.png|18px|Bauxite]] " .. ship["dismantle"][4]
  local scrapinfo = scrapfuel .. " " .. scrapammo .. " " .. scrapsteel .. " " .. scrapbauxite
  local row12 = row12 .. RscHeader .. "Dismantle</th>" .. RscData .. scrapinfo .. "</td></tr>"
  -- Modernization
  local modFP = "[[File:IcoAtkRemodel.png|25px|Firepower]] " .. ship["modernization"][1]
  local modTorp = "[[File:IcoTorpedoRemodel.png|25px|Torpedo]] " .. ship["modernization"][2]
  local modAA = "[[File:IcoAARemodel.png|25px|Anti-Air]] " .. ship["modernization"][3]
  local modArmor = "[[File:IcoArmorRemodel.png|25px|Armor]] " .. ship["modernization"][4]
  local modLuck = ""
  if ship["modernization"][5] ~= nil and ship["modernization"][5] ~= "" then
    modLuck = "[[File:IcoLuckRemodel.png|25px|Luck]] " .. ship["modernization"][5]
  end
  local modInfo = modFP .. " " .. modTorp .. " " .. modAA .. " " .. modArmor
  if modLuck ~= "" then
    modInfo = modInfo .. " " .. modLuck
  end
  local row13 = "<tr>" .. RscHeader .. "Modernization</th>" .. RscData2 .. modInfo .. "</td></tr>"
  return row13 .. row11 .. row12
end

local function renderArtists(ship)
  local RscHeader =
    '<th style="width: 25%; white-space: nowrap; {{border-radius|12px 4px 4px 12px}} background-color: #3baef5; color: #ffffff; padding-left: 5px; padding-right: 5px; text-align: right;">'
  local RscData = '<td style="width: 25%; white-space: nowrap; text-align: center;">'
  local illustrator =
    ship["artist"] ~= "Unknown" and ship["artist"] ~= "" and
    ("[[:Category:" .. ship["artist"] .. "|" .. ship["artist"] .. "]]") or
    "Unknown"
  local voiceactor =
    ship["seiyuu"] ~= "Unknown" and ship["seiyuu"] ~= "" and
    ("[[:Category:" .. ship["seiyuu"] .. "|" .. ship["seiyuu"] .. "]]") or
    "Unknown"
  return RscHeader ..
    "Artist</th>" .. RscData .. illustrator .. "</td>" .. RscHeader .. "Seiyuu</th>" .. RscData .. voiceactor .. "</td>"
end

local function renderCategories(ship)
  local categories = "[[Category:Ships]][[Category:" .. ship["class"] .. " Class]][[Category:" .. ship["type"] .. "s]]"
  if ship["artist"] ~= "Unknown" and ship["artist"] ~= "" then
    categories = categories .. "[[Category:" .. ship["artist"] .. "]]"
  end
  if ship["seiyuu"] ~= "Unknown" and ship["seiyuu"] ~= "" then
    categories = categories .. "[[Category:" .. ship["seiyuu"] .. "]]"
  end
  return categories
end

local function render(frame)
  local ShipData = mw.loadData("Module:Data/Ship")
  local shipNum = frame.args[1]
  local ship = ShipData[shipNum]
  return '<div style="display:inline-block;vertical-align:top"><table style="{{border-radius|10px 10px 10px 10px}} border:1px solid #aaaaaa;min-width:495px"><tr><td>' ..
    renderStats(ship, shipNum) ..
      "</td></tr><tr><td>" ..
        renderEquipment(ship) ..
          '<table style="width:100%">' ..
            renderModernization(ship) ..
              renderArtists(ship) .. "</table></td></tr></table></div>" .. renderCategories(ship)
end

return {KanmusuInfo = render}