Jump to content

Module:ItemCategoryTable: Difference between revisions

From Apogea Wiki
Dane (talk | contribs)
Use centralized Module:ItemTypes for type definitions (via update-page on MediaWiki MCP Server)
Dane (talk | contribs)
No edit summary
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
local p = {}
local p = {}
local ItemTypes = require('Module:ItemTypes')
local ItemConfig = require('Module:ItemConfig')


-- Query items by type from Cargo
-- Query items by type from Cargo (type is a List field, requires HOLDS)
local function getItemsByType(itemType)
local function getItemsByType(itemType)
     local tables = 'Items'
     local tables = 'Items'
     local fields = 'name,sprite,type,weight,damage,armor,defense,health,mana,ability,magic,rng,move_speed,attack_speed,health_regen,mana_regen,container,size,rarity'
     local fields = ItemConfig.cargoFields.itemsTable
     local args = {
     local args = {
         where = 'type LIKE "%' .. itemType .. '%"',
         where = 'type HOLDS "' .. itemType .. '"',
         orderBy = 'name',
         orderBy = 'name',
         limit = 500
         limit = 500
     }
     }
   
 
     return mw.ext.cargo.query(tables, fields, args)
     return mw.ext.cargo.query(tables, fields, args)
end
end
Line 18: Line 18:
local function getItemsByTypes(types)
local function getItemsByTypes(types)
     local tables = 'Items'
     local tables = 'Items'
     local fields = 'name,sprite,type,weight,damage,armor,defense,health,mana,ability,magic,rng,move_speed,attack_speed,health_regen,mana_regen,container,size,rarity'
     local fields = ItemConfig.cargoFields.itemsTable
   
 
     -- Build OR conditions for each type
     -- Build OR conditions for each type (using HOLDS for List field)
     local conditions = {}
     local conditions = {}
     for _, t in ipairs(types) do
     for _, t in ipairs(types) do
         table.insert(conditions, 'type LIKE "%' .. t .. '%"')
         table.insert(conditions, 'type HOLDS "' .. t .. '"')
     end
     end
   
 
     local args = {
     local args = {
         where = table.concat(conditions, ' OR '),
         where = table.concat(conditions, ' OR '),
Line 31: Line 31:
         limit = 500
         limit = 500
     }
     }
   
 
     return mw.ext.cargo.query(tables, fields, args)
     return mw.ext.cargo.query(tables, fields, args)
end
end
Line 38: Line 38:
local function getAllItems()
local function getAllItems()
     local tables = 'Items'
     local tables = 'Items'
     local fields = 'name,sprite,type,weight,damage,armor,defense,health,mana,ability,magic,rng,move_speed,attack_speed,health_regen,mana_regen,container,size,rarity'
     local fields = ItemConfig.cargoFields.itemsTable
     local args = {
     local args = {
         orderBy = 'name',
         orderBy = 'name',
         limit = 500
         limit = 500
     }
     }
   
 
     return mw.ext.cargo.query(tables, fields, args)
     return mw.ext.cargo.query(tables, fields, args)
end
end
Line 70: Line 70:
           statNum(item.attack_speed)
           statNum(item.attack_speed)
end
end
-- Sort column mapping
local sortColumns = {
    name = function(item) return item.name or item._pageName or "" end,
    type = function(item) return item.type or "" end,
    slots = function(item) return statNum(item.container) end,
    container = function(item) return statNum(item.container) end,
    weight = function(item) return statNum(item.weight) end,
    damage = function(item) return statNum(item.damage) end,
    armor = function(item) return statNum(item.armor) end,
    defense = function(item) return statNum(item.defense) end,
    health = function(item) return statNum(item.health) end,
    mana = function(item) return statNum(item.mana) end,
    ability = function(item) return statNum(item.ability) end,
    magic = function(item) return statNum(item.magic) end,
    rng = function(item) return statNum(item.rng) end,
    move_speed = function(item) return statNum(item.move_speed) end,
    attack_speed = function(item) return statNum(item.attack_speed) end,
    power = function(item) return item._power end,
    total = function(item) return item._power end
}


function p.render(frame)
function p.render(frame)
     local args = frame:getParent().args
     local args = frame.args
     local categoryName = args[1] or args.category or mw.title.getCurrentTitle().text:gsub("^Category:", "")
     local categoryName = args[1] or args.category or mw.title.getCurrentTitle().text:gsub("^Category:", "")
      
     local sortBy = args.sort or args.sortby
    local sortDir = args.dir or args.sortdir or "desc"
 
     -- Check if this is a parent category or all items
     -- Check if this is a parent category or all items
     local isAllItems = (categoryName == "Items")
     local isAllItems = (categoryName == "Items")
     local isParent = ItemTypes.isParentCategory(categoryName) or isAllItems
     local isParent = ItemConfig.isParentCategory(categoryName) or isAllItems
     local isContainers = (categoryName == "Containers")
     local isContainers = (categoryName == "Containers")
     local items
     local items
   
 
     if isAllItems then
     if isAllItems then
         items = getAllItems()
         items = getAllItems()
     elseif ItemTypes.isParentCategory(categoryName) then
     elseif ItemConfig.isParentCategory(categoryName) then
         items = getItemsByTypes(ItemTypes.getChildTypes(categoryName))
         items = getItemsByTypes(ItemConfig.getChildTypes(categoryName))
     else
     else
         local itemType = ItemTypes.singularize(categoryName)
         local itemType = ItemConfig.singularize(categoryName)
         items = getItemsByType(itemType)
         items = getItemsByType(itemType)
     end
     end
   
 
     if not items or #items == 0 then
     if not items or #items == 0 then
         return '<p class="mw-empty">No items found.</p>'
         return '<p class="mw-empty">No items found.</p>'
     end
     end
   
 
     -- Calculate power for each item and sort
     -- Calculate power for each item
     for _, item in ipairs(items) do
     for _, item in ipairs(items) do
         item._power = calcPower(item)
         item._power = calcPower(item)
     end
     end
   
 
     -- Sort by slots for containers, otherwise by power
     -- Determine sort column
     if isContainers then
    local sortFunc = nil
         table.sort(items, function(a, b) return statNum(a.container) > statNum(b.container) end)
     if sortBy and sortColumns[sortBy] then
        sortFunc = sortColumns[sortBy]
    elseif isContainers then
         sortFunc = sortColumns.slots
     else
     else
         table.sort(items, function(a, b) return a._power > b._power end)
         sortFunc = sortColumns.power
     end
     end
      
 
     -- Sort items
    local ascending = (sortDir == "asc")
    table.sort(items, function(a, b)
        local valA = sortFunc(a)
        local valB = sortFunc(b)
        if ascending then
            return valA < valB
        else
            return valA > valB
        end
    end)
 
     -- Build sortable table
     -- Build sortable table
     local tbl = mw.html.create('table')
     local tbl = mw.html.create('table')
Line 111: Line 149:
       :addClass('sortable')
       :addClass('sortable')
       :css('width', '100%')
       :css('width', '100%')
   
 
     -- Header row
     -- Header row
     local header = tbl:tag('tr')
     local header = tbl:tag('tr')
Line 137: Line 175:
     header:tag('th'):attr('title', 'Attack Speed'):wikitext('AS')
     header:tag('th'):attr('title', 'Attack Speed'):wikitext('AS')
     header:tag('th'):attr('title', 'Total Stats'):wikitext('Total')
     header:tag('th'):attr('title', 'Total Stats'):wikitext('Total')
   
 
     -- Data rows
     -- Data rows
     for _, item in ipairs(items) do
     for _, item in ipairs(items) do
         local row = tbl:tag('tr')
         local row = tbl:tag('tr')
       
 
         -- Icon column
         -- Icon column
         local iconCell = row:tag('td')
         local iconCell = row:tag('td')
Line 150: Line 188:
             iconCell:wikitext(frame:preprocess('{{Sprite|' .. sprite .. '|x2}}'))
             iconCell:wikitext(frame:preprocess('{{Sprite|' .. sprite .. '|x2}}'))
         end
         end
       
 
         -- Item name column
         -- Item name column
         local itemName = item.name or "Unknown"
         local itemName = item.name or "Unknown"
         row:tag('td'):wikitext('[[' .. itemName .. ']]')
         row:tag('td'):wikitext('[[' .. itemName .. ']]')
       
 
         -- Type column (for parent categories)
         -- Type column (for parent categories)
         if isParent then
         if isParent then
             local typeCategory = ItemTypes.pluralize(item.type or "")
             local typeCategory = ItemConfig.pluralize(item.type or "")
             row:tag('td'):wikitext('[[:Category:' .. typeCategory .. '|' .. (item.type or "") .. ']]')
             row:tag('td'):wikitext('[[:Category:' .. typeCategory .. '|' .. (item.type or "") .. ']]')
         end
         end
       
 
         -- Slots column (for containers)
         -- Slots column (for containers)
         if isContainers then
         if isContainers then
             row:tag('td'):css('text-align', 'right'):wikitext(stat(item.container))
             row:tag('td'):css('text-align', 'right'):wikitext(stat(item.container))
         end
         end
       
 
         -- Stats
         -- Stats
         row:tag('td'):css('text-align', 'right'):wikitext(stat(item.weight))
         row:tag('td'):css('text-align', 'right'):wikitext(stat(item.weight))
Line 180: Line 218:
         row:tag('td'):css('text-align', 'right'):wikitext(item._power)
         row:tag('td'):css('text-align', 'right'):wikitext(item._power)
     end
     end
   
 
     return tostring(tbl)
     return tostring(tbl)
end
end


return p
return p

Latest revision as of 21:15, 1 February 2026

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

local p = {}
local ItemConfig = require('Module:ItemConfig')

-- Query items by type from Cargo (type is a List field, requires HOLDS)
local function getItemsByType(itemType)
    local tables = 'Items'
    local fields = ItemConfig.cargoFields.itemsTable
    local args = {
        where = 'type HOLDS "' .. itemType .. '"',
        orderBy = 'name',
        limit = 500
    }

    return mw.ext.cargo.query(tables, fields, args)
end

-- Query items by multiple types
local function getItemsByTypes(types)
    local tables = 'Items'
    local fields = ItemConfig.cargoFields.itemsTable

    -- Build OR conditions for each type (using HOLDS for List field)
    local conditions = {}
    for _, t in ipairs(types) do
        table.insert(conditions, 'type HOLDS "' .. t .. '"')
    end

    local args = {
        where = table.concat(conditions, ' OR '),
        orderBy = 'name',
        limit = 500
    }

    return mw.ext.cargo.query(tables, fields, args)
end

-- Query all items
local function getAllItems()
    local tables = 'Items'
    local fields = ItemConfig.cargoFields.itemsTable
    local args = {
        orderBy = 'name',
        limit = 500
    }

    return mw.ext.cargo.query(tables, fields, args)
end

-- Get numeric value from stat (0 if empty)
local function statNum(value)
    if value and value ~= "" then
        return tonumber(value) or 0
    end
    return 0
end

-- Format stat value (return 0 if empty)
local function stat(value)
    if value and value ~= "" then
        return value
    end
    return "0"
end

-- Calculate total stat power for an item
local function calcPower(item)
    return statNum(item.damage) + statNum(item.armor) + statNum(item.defense) +
           statNum(item.health) + statNum(item.mana) + statNum(item.ability) +
           statNum(item.magic) + statNum(item.rng) + statNum(item.move_speed) +
           statNum(item.attack_speed)
end

-- Sort column mapping
local sortColumns = {
    name = function(item) return item.name or item._pageName or "" end,
    type = function(item) return item.type or "" end,
    slots = function(item) return statNum(item.container) end,
    container = function(item) return statNum(item.container) end,
    weight = function(item) return statNum(item.weight) end,
    damage = function(item) return statNum(item.damage) end,
    armor = function(item) return statNum(item.armor) end,
    defense = function(item) return statNum(item.defense) end,
    health = function(item) return statNum(item.health) end,
    mana = function(item) return statNum(item.mana) end,
    ability = function(item) return statNum(item.ability) end,
    magic = function(item) return statNum(item.magic) end,
    rng = function(item) return statNum(item.rng) end,
    move_speed = function(item) return statNum(item.move_speed) end,
    attack_speed = function(item) return statNum(item.attack_speed) end,
    power = function(item) return item._power end,
    total = function(item) return item._power end
}

function p.render(frame)
    local args = frame.args
    local categoryName = args[1] or args.category or mw.title.getCurrentTitle().text:gsub("^Category:", "")
    local sortBy = args.sort or args.sortby
    local sortDir = args.dir or args.sortdir or "desc"

    -- Check if this is a parent category or all items
    local isAllItems = (categoryName == "Items")
    local isParent = ItemConfig.isParentCategory(categoryName) or isAllItems
    local isContainers = (categoryName == "Containers")
    local items

    if isAllItems then
        items = getAllItems()
    elseif ItemConfig.isParentCategory(categoryName) then
        items = getItemsByTypes(ItemConfig.getChildTypes(categoryName))
    else
        local itemType = ItemConfig.singularize(categoryName)
        items = getItemsByType(itemType)
    end

    if not items or #items == 0 then
        return '<p class="mw-empty">No items found.</p>'
    end

    -- Calculate power for each item
    for _, item in ipairs(items) do
        item._power = calcPower(item)
    end

    -- Determine sort column
    local sortFunc = nil
    if sortBy and sortColumns[sortBy] then
        sortFunc = sortColumns[sortBy]
    elseif isContainers then
        sortFunc = sortColumns.slots
    else
        sortFunc = sortColumns.power
    end

    -- Sort items
    local ascending = (sortDir == "asc")
    table.sort(items, function(a, b)
        local valA = sortFunc(a)
        local valB = sortFunc(b)
        if ascending then
            return valA < valB
        else
            return valA > valB
        end
    end)

    -- Build sortable table
    local tbl = mw.html.create('table')
    tbl:addClass('wikitable')
       :addClass('sortable')
       :css('width', '100%')

    -- Header row
    local header = tbl:tag('tr')
    header:tag('th')
        :css('width', '64px')
        :addClass('unsortable')
        :wikitext('')
    header:tag('th'):wikitext('Item')
    if isParent then
        header:tag('th'):wikitext('Type')
    end
    if isContainers then
        header:tag('th'):attr('title', 'Container Slots'):wikitext('Slots')
    end
    header:tag('th'):attr('title', 'Weight'):wikitext('WGT')
    header:tag('th'):attr('title', 'Damage'):wikitext('DMG')
    header:tag('th'):attr('title', 'Armor'):wikitext('ARM')
    header:tag('th'):attr('title', 'Defense'):wikitext('DEF')
    header:tag('th'):attr('title', 'Health'):wikitext('HP')
    header:tag('th'):attr('title', 'Mana'):wikitext('MP')
    header:tag('th'):attr('title', 'Ability'):wikitext('ABL')
    header:tag('th'):attr('title', 'Magic'):wikitext('MAG')
    header:tag('th'):attr('title', 'Range'):wikitext('RNG')
    header:tag('th'):attr('title', 'Move Speed'):wikitext('MS')
    header:tag('th'):attr('title', 'Attack Speed'):wikitext('AS')
    header:tag('th'):attr('title', 'Total Stats'):wikitext('Total')

    -- Data rows
    for _, item in ipairs(items) do
        local row = tbl:tag('tr')

        -- Icon column
        local iconCell = row:tag('td')
            :css('width', '64px')
            :css('text-align', 'center')
        local sprite = item.sprite or item.name or "Unknown"
        if sprite and sprite ~= "" then
            iconCell:wikitext(frame:preprocess('{{Sprite|' .. sprite .. '|x2}}'))
        end

        -- Item name column
        local itemName = item.name or "Unknown"
        row:tag('td'):wikitext('[[' .. itemName .. ']]')

        -- Type column (for parent categories)
        if isParent then
            local typeCategory = ItemConfig.pluralize(item.type or "")
            row:tag('td'):wikitext('[[:Category:' .. typeCategory .. '|' .. (item.type or "") .. ']]')
        end

        -- Slots column (for containers)
        if isContainers then
            row:tag('td'):css('text-align', 'right'):wikitext(stat(item.container))
        end

        -- Stats
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.weight))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.damage))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.armor))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.defense))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.health))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.mana))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.ability))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.magic))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.rng))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.move_speed))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(item.attack_speed))
        row:tag('td'):css('text-align', 'right'):wikitext(item._power)
    end

    return tostring(tbl)
end

return p