Module:Data tables: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
>Illviljan
(Adding generic stats)
No edit summary
 
(40 intermediate revisions by 6 users not shown)
Line 1: Line 1:
--[[
--[[
     Module for data tables
     Module for data tables
      
 
     Attempts to create advanced infoboxes in a standardized way.
]]
]]


local getArgs = require('Module:Arguments').getArgs
local getArgs = require('Module:Arguments').getArgs
local m_util = require('Module:Util')
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
local m_game = require('Module:Game')
local m_game = require('Module:Game')
local f_infocard = require('Module:Infocard')._main
local f_infocard = require('Module:Infocard')._main
Line 18: Line 20:
         id = 'Id',
         id = 'Id',
     },
     },
     character_shared_stats = {
     generic_stats = {
         number = 'Number',
         name = 'Name',
         id = 'Id',
         id = 'Id',
         text = 'Text',
         str_id = 'Str_id',
        str = 'Strength',
        dex = 'Dexterity',
        int = 'Intelligence',
        stat_text = 'Text',
         value = 'Value',
         value = 'Value',
     },
     },
Line 51: Line 57:
         match_race = 'race season',
         match_race = 'race season',
         number_of_events = 'Number of events',
         number_of_events = 'Number of events',
         price = 'Price',
         prize = 'Prize',
         rewards = 'Rewards',
         rewards = 'Rewards',
         links = 'Links',
         links = 'Links',
     },
     },
}
}
-- game
m_game.constants.characters.shared_stats = {
    {
        id    = 'accuracy_rating_per_level',
        value  = 2,
        text  = '+2 [[Accuracy Rating]] per [[Level]]',
    },
    {
        id    = 'base_attack_speed_+%_per_frenzy_charge',
        value  = 4,
        text  = '4% increased [[Attack Speed]] per [[Frenzy Charge]]',
    },
    {
        id    = 'base_cast_speed_+%_per_frenzy_charge',
        value  = 4,
        text  = '4% increased [[Cast Speed]] per [[Frenzy Charge]]',
    },
    {
        id    = 'base_critical_strike_multiplier',
        value  = 150,
        text  = 'Base [[Critical Strike Multiplier]]: 150',
    },
    {
        id    = 'base_evasion_rating',
        value  = 53,
        text  = '53 to [[Evasion Rating]]',
    },
    {
        id    = 'base_maximum_chaos_damage_resistance_%',
        value  = 75,
        text  = '75% to maximum [[Chaos Resistance]]',
    },
    {
        id    = 'base_maximum_cold_damage_resistance_%',
        value  = 75,
        text  = '75% to maximum [[Cold Resistance]]',
    },
    {
        id    = 'base_maximum_fire_damage_resistance_%',
        value  = 75,
        text  = '75% to maximum [[Fire Resistance]]',
    },
    {
        id    = 'base_maximum_lightning_damage_resistance_%',
        value  = 75,
        text  = '75% to maximum [[Lightning Resistance]]',
    },
    {
        id    = 'base_number_of_remote_mines_allowed',
        value = 5,
        text  = 'Can set up to 5 remote [[mine|mines]]',
    },
    {
        id    = 'base_number_of_totems_allowed',
        value = 1,
        text  = 'Can summon up to 1 [[totem]]',
    },
    {
        id    = 'base_number_of_traps_allowed',
        value = 3,
        text  = 'Can set up to 3 [[trap|traps]]',
    },
    {
        id    = 'block_while_dual_wielding_%',
        value = 15,
        text  = '15% additional [[Block]] Chance while [[Dual Wield|Dual Wielding]]',
    },
    {
        id    = 'critical_strike_chance_+%_per_power_charge',
        value = 40,
        text  = '40% increased [[Critical Strike Chance]] per [[Power Charge]]',
    },
    {
        id    = 'damage_+%_per_10_rampage_stacks',
        value = 2,
        text  = '2% increased Damage per 10 [[Rampage]] Stacks'
    },
    {
        id    = 'damage_+%_per_frenzy_charge_final',
        value = 4,
        text  = '4% more Damage per [[Frenzy Charge]]',
    },
    {
        id    = 'dexterity_per_level',
        value = 0,
        text  = '+0 [[Dexterity]] per [[Level]]'
    },
    {
        id    = 'dual_wield_inherent_attack_speed_+%_final',
        value = 10,
        text  = '10% more [[Attack Speed]] while [[Dual Wield|Dual Wielding]]',
    },
    {
        id    = 'dual_wield_inherent_physical_attack_damage_+%_final',
        value = 20,
        text  = '20% more Attack [[Physical Damage]] while [[Dual Wield|Dual Wielding]]',
    },
    {
        id    = 'energy_shield_recharge_rate_per_minute_%',
        value = 1200,
        text  = '20.0% of [[Energy Shield]] Recharged per second',
    },
    {
        id    = 'evasion_rating_per_level',
        value = 300,
        text  = '+3.0 [[Evasion Rating]] per [[Level]]',
    },
    {
        id    = 'intelligence_per_level',
        value = 0,
        text  = '+0 [[Intelligence]] per [[Level]]',
    },
    {
        id    = 'is_player',
        value = 1,
        text  = 'Is player',
    },
    {
        id    = 'level',
        value = 1,
        text  = '[[Level]] 1'
    },
    {
        id    = 'life_per_level',
        value = 12,
        text  = '+12 [[Life]] per [[Level]]',
    },
    {
        id    = 'mana_per_level',
        value = 6,
        text  = '+6 [[Mana]] per [[Level]]',
    },
    {
        id    = 'mana_regeneration_rate_per_minute_%',
        value = 105,
        text  = '1.75% of [[Mana]] Regenerated per second'
    },
    {
        id    = 'max_corrupted_blood_rain_stacks',
        value = 20,
        text  = 'Can have up to 20 [[Corrupted Blood]] Rain Stacks',
    },
    {
        id    = 'max_corrupted_blood_stacks',
        value = 20,
        text  = 'Can have up to 20 [[Corrupted Blood]] Stacks',
    },
    {
        id    = 'max_endurance_charges',
        value = 3,
        text  = '3 Maximum [[Endurance Charge|Endurance Charges]]',
    },
    {
        id    = 'max_frenzy_charges',
        value = 3,
        text  = '3 Maximum [[Frenzy Charge|Frenzy Charges]]',
    },
    {
        id    = 'max_fuse_arrow_orbs',
        value = 5,
        text  = 'Can have up to 5 [[Explosive Arrow]] Stacks',
    },
    {
        id    = 'max_power_charges',
        value = 3,
        text  = '3 Maximum [[Power Charge|Power Charges]]',
    },
    {
        id    = 'max_rampage_stacks',
        value = 1000,
        text  = 'Can have up to 1000 [[Rampage]] Stacks',
    },
    {
        id    = 'maximum_block_%',
        value = 75,
        text  = '75% to maximum [[Block]] Chance',
    },
    {
        id    = 'maximum_dodge_chance_%',
        value = 75,
        text  = 'Can have up to 75% [[Dodge]] Chance',
    },
    {
        id    = 'maximum_life_leech_rate_%_per_minute',
        value = 1200,
        text  = '20.0% of maximum [[Life]] per second to maximum [[Life]] [[Leech]] rate',
    },
    {
        id    = 'maximum_mana_leech_rate_%_per_minute',
        value = 1200,
        text  = '20.0% of maximum [[Mana]] per second to maximum [[Mana]] [[Leech]] rate',
    },
    {
        id    = 'maximum_physical_damage_reduction_%',
        value = 90,
        text  = 'Can have up to 90% maximum [[Physical Damage]] Reduction',
    },
    {
        id    = 'maximum_spell_dodge_chance_%',
        value = 75,
        text  = 'Can have up to 75% [[Spell Dodge]] Chance',
    },
    {
        id    = 'minion_damage_+%_per_10_rampage_stacks',
        value = 2,
        text  = '[[Minion|Minions]] deal 2% increased Damage per 10 [[Rampage]] Stacks',
    },
    {
        id    = 'minion_movement_velocity_+%_per_10_rampage_stacks',
        value = 1,
        text  = '[[Minion|Minions]] gain 1% increased [[Movement Speed]] per 10 [[Rampage]] Stacks',
    },
    {
        id    = 'movement_velocity_+%_per_10_rampage_stacks',
        value = 1,
        text  = '1% increased [[Movement Speed]] per 10 [[Rampage]] Stacks',
    },
    {
        id    = 'physical_damage_reduction_%_per_endurance_charge',
        value = 4,
        text  = '4% [[Physical Damage]] Reduction per [[Endurance Charge]]',
    },
    {
        id    = 'pvp_shield_damage_+%_final',
        value = -15,
        text  = '15% less Shield Damage in [[PvP]]',
    },
    {
        id    = 'resist_all_elements_%_per_endurance_charge',
        value = 4,
        text  = '4% to all [[Elemental Resistance|Elemental Resistances]] per [[Endurance Charge]]',
    },
    {
        id    = 'strength_per_level',
        value = 0,
        text  = '+0 [[Strength]] per [[Level]]',
    },
}


-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------
Line 305: Line 71:
     --[[
     --[[
     Format dates in correct and useable form.
     Format dates in correct and useable form.
      
 
     value = date string
    Parameters
     args = table of extra args.
     ----------
   
     value : String, required
        Date
     args : Table
        Table with extra formatting args.
 
     To do:
     To do:
     Remove hours if it isn't specified.
     Remove hours if it isn't specified.
     ]]
     ]]
   
 
     local args = args or {}
     local args = args or {}
   
 
     -- List of allowed extra arguments:
     -- List of allowed extra arguments:
     local arg_list = {
     local arg_list = {
         format = {
         format = {
             default = 'Y-m-d H:i:s',
             default = 'Y-m-d H:i:s',
             cargo = 'Y-m-d H:i:s',
             cargo   = 'Y-m-d H:i:s',
            no_time = 'Y-m-d',
         },
         },
     }
     }
      
 
     local date_format = arg_list.format.default
     local date_format = arg_list['format']['default']
     local timestamp = mw_language:formatDate(date_format, value)
 
    -- If the time is 00:00:00 then assume that the time isn't defined:
    if mw_language:formatDate('H:i:s', timestamp) == '00:00:00' then
        date_format = arg_list['format']['no_time']
    end
 
    -- Add the extra arguments:
     for i,v in pairs(args) do
     for i,v in pairs(args) do
         if i == 'format' then
         if i == 'format' then
             date_format = arg_list[i][v]          
             date_format = arg_list[i][v]
         end
         end
     end
     end
    -- Return the final timestamp format:
     local out
     local out
     if value ~= nil then
     if value ~= nil then
         out = mw_language:formatDate(date_format, value)
         out = mw_language:formatDate(date_format, timestamp)
    else
        out =  nil
     end
     end
   
 
     return out
     return out
end
end
Line 341: Line 120:
function h.timezone(str)
function h.timezone(str)
     --[[
     --[[
     Check if the string contains Z at the end, if it does it implies  
     Check if the string contains Z at the end, if it does it implies
     the time is in UTC and then return UTC.
     the time is in UTC and then return UTC.
     ]]
     ]]
      
 
if str ~= nil and str:sub(-1,-1) == 'Z' then
     local out = ''
return 'UTC'
    if str ~= nil and str:sub(-1,-1) == 'Z' then
else
        out = 'UTC'
return ''
    end
end
 
    return out
end
end


Line 355: Line 135:
     --[[
     --[[
     Returns a Cargo query of all the results.
     Returns a Cargo query of all the results.
   
 
     tpl_args should include these keys:
     tpl_args should include these keys:
     tpl_args.tables
     tpl_args.tables
     tpl_args.fields
     tpl_args.fields
     tpl_args.q_*
     tpl_args.q_*
   
 
     ]]
     ]]
   
 
     local tables = m_util.string.split(tpl_args.tables, ', ')
     local tables = m_util.string.split(tpl_args.tables, ', ')
     local fields = m_util.string.split(tpl_args.fields, ', ')
     local fields = m_util.string.split(tpl_args.fields, ', ')
   
 
     -- Parse query arguments
     -- Parse query arguments
     local query = {
     local query = {
     }
     }
     for key, value in pairs(tpl_args) do  
     for key, value in pairs(tpl_args) do
         if string.sub(key, 0, 2) == 'q_' then
         if string.sub(key, 0, 2) == 'q_' then
             query[string.sub(key, 3)] = value
             query[string.sub(key, 3)] = value
         end
         end
     end
     end
   
 
     -- Query cargo rows:
     -- Query cargo rows:
     local results = m_util.cargo.query(tables, fields, query, args)
     local results = m_cargo.query(tables, fields, query)
   
 
     return results
     return results
end
end


function h.parse_map(tpl_args, frame, map)
function h.parse_map(tpl_args, frame, tbldef)
     --[[
     --[[
         Parse the map
         Parse the map
       
 
         Input:
         Input:
       
 
     ]]
     ]]
     local cargo_data = {
     local cargo_data = {
         _table = map.main.table,
         _table = tbldef.table,
     }
     }
     for _, key in pairs(map.main.parse_order) do
     for _, key in pairs(tbldef.parse_order) do
         local data = map.main.fields[key]
         local data = tbldef.fields[key]
         local value  
         local value
         if data.func ~= nil then
         if data.func ~= nil then
             if data.name then
             if data.name then
Line 403: Line 183:
             value = tpl_args[data.name]
             value = tpl_args[data.name]
         end
         end
       
 
         tpl_args[key] = value
         tpl_args[key] = value


Line 414: Line 194:
         end
         end
     end
     end
   
 
     local out = {
     local out = {
         tpl_args = tpl_args,
         tpl_args = tpl_args,
         cargo_data = cargo_data,
         cargo_data = cargo_data,
     }
     }
   
 
     return out
     return out
end
end
Line 425: Line 205:
h.parse_stat_args = function(tpl_args, args)
h.parse_stat_args = function(tpl_args, args)
     --[[
     --[[
     Parse template args that starts with stat.+ and return them as a  
     Parse template args that starts with stat.+ and return them as a
     array.
     array.
   
 
     ]]
     ]]
   
 
     out = {}
     out = {}
     for key, value in pairs(tpl_args) do  
     for key, value in pairs(tpl_args) do
         local n,k = string.match(key, 'stat(%d+)_(%w+)')
         if string.sub(key, 0, 4) == 'stat' then
       
            local n,k = string.match(key, 'stat(%d+)_(.+)')
        if out[n] == nil then  
            n = tostring(n)
            out[n] = {}  
            if out[n] == nil then
                out[n] = {}
            end
            if n ~= nil and k ~= nil then
                out[n][k] = value
            else
                error(string.format(
                    'Wrong stat argument format. The template argument "%s" matched "%s" and "%s".',
                    key or 'n/a', n or 'n/a', k or 'n/a'
                    )
                )
            end
         end
         end
       
        out[n][k] = value
     end
     end


     return out
     return out
end
end


-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------
Line 448: Line 238:
-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------


local generic_stats_map = {
local tables = {
     main = {
     generic_stats = {
         table = 'generic_stats',
         table = 'generic_stats',
         order = {},
         order = {},
         parse_order = {'id', 'stat_text', 'value'},
         parse_order = {'name', 'id', 'stat_text', 'value'},
         fields = {
         fields = {
            name = {
                name = 'name',
                field = 'name',
                type = 'String',
                wikitext = i18n.generic_stats.name,
            },
             id = {
             id = {
                 name = 'row',
                 name = 'row',
                 field = 'id',
                 field = 'id',
                 type = 'String',
                 type = 'String',
                 wikitext = i18n.character_shared_stats.id,
                 wikitext = i18n.generic_stats.id,
                 func = function(tpl_args, frame, value)
                 func = function(tpl_args, frame, value)
                     return tpl_args.stats[value].id
                     return tpl_args.stats[value].id
Line 467: Line 263:
                 field = 'stat_text',
                 field = 'stat_text',
                 type = 'Wikitext',
                 type = 'Wikitext',
                 wikitext = i18n.character_shared_stats.text,
                 wikitext = i18n.generic_stats.stat_text,
                 func = function(tpl_args, frame, value)
                 func = function(tpl_args, frame, value)
                     return tpl_args.stats[value].stat_text
                     return tpl_args.stats[value].stat_text
Line 476: Line 272:
                 field = 'value',
                 field = 'value',
                 type = 'Integer',
                 type = 'Integer',
                 wikitext = i18n.character_shared_stats.value,
                 wikitext = i18n.generic_stats.value,
                 func = function(tpl_args, frame, value)
                 func = function(tpl_args, frame, val)
                     return tpl_args.stats[value].value
                     return tpl_args.stats[val].value
                 end,
                 end,
             },
             },
Line 486: Line 282:


-- Declare cargo table:
-- Declare cargo table:
p.declare_generic_stats = m_util.cargo.declare_factory{
p.declare_generic_stats = m_cargo.declare_factory{
     data=generic_stats_map.main,
     data=tables.generic_stats,
}
}


-- Attach cargo table:
p.store_data = m_cargo.store_from_lua{tables=tables, module='Data tables'}
p.attach_generic_stats = m_util.cargo.attach_factory{
    data=generic_stats_map.main,
}
 
function p.generic_stats(frame)
    --[[
    Displays a infobox and stores cargo data for characters shared stats
    = p.generic_stats{
        stat1_id = 'accuracy_rating_per_level',
        stat1_value = 2,
        stat1_stat_text = '+2 Accuracy Rating per Level',
        stat12_id = 'base_attack_speed_+%_per_frenzy_charge',
        stat12_value = 4,
        stat12_stat_text = '4% increased Attack Speed per Frenzy Charge',
    }
    ]]
   
    -- Get template args:
    local tpl_args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)
    tpl_args.stats = h.parse_stat_args(tpl_args)
 
    -- Parse map and store cargo fields:
    local map = generic_stats_map
    for i,v in ipairs(tpl_args.stats) do
        tpl_args.row = i
        local parsed_map = h.parse_map(tpl_args, frame, map)
        tpl_args = parsed_map.tpl_args
        local cargo_data = parsed_map.cargo_data
        m_util.cargo.store(frame, cargo_data)
    end
   
    -- Main sections, loop through
    local tbl = mw.html.create('table')
    for _, key in ipairs(map.main.order) do
        local data = map.main.fields[key]
       
        if data.display == nil then
            text = tpl_args[key]
        else
            text = data.display(tpl_args, frame, tpl_args[key])
        end
       
        if text ~= nil then         
            tbl
                :tag('tr')
                    :tag('th')
                        :wikitext(data.wikitext)
                        :done()
                    :tag('td')
                        :wikitext(text)
                        :done()
                    :done()
        elseif text then
            tbl
                :tag('tr')
                    :tag('td')
                        -- :attr('colspan', '2')
                        :wikitext(text)
                        :done()
                    :done()
        end
    end
   
    -- Output Infocard
local infocard_args = {
['class'] = 'character_shared_stats',
['header'] = 'Character',
['subheader'] = nil,
[1] = '[[File:Character shared_stats.png|250px]]',
         
[2] = tostring(tbl),
    }
   
    -- Add categories:
    local cats = {
        'Data pages'
    }
   
    return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
end


-- --------------------------------------------------------------------
-- Template: Character class
-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------
-- Template: Character shared stats
tables.character_classes = {
-- ---------------------------------------------------------------------
     table = 'character_classes',
 
    order = {'flavour_text'},
local character_shared_stats_map = {
    parse_order = {'name', 'flavour_text', 'id', 'str_id', 'str', 'dex', 'int'},
     main = {
    fields = {
        table = 'character_shared_stats',
        -- Header:
        order = {},
         name = {
        parse_order = {'id', 'text', 'value'},
             name = 'name',
         fields = {
            field = 'name',
             id = {
            type = 'String',
                name = 'row',
            wikitext = i18n.character_class.name,
                 field = 'id',
        },
                type = 'String',
        -- Main text:
                wikitext = i18n.character_shared_stats.id,
        flavour_text = {
                func = function(tpl_args, frame, value)
            name = 'flavour_text',
                    return m_game.constants.characters.shared_stats[value].id
            field = 'flavour_text',
                end,
            type = 'String',
            },
            display = function(tpl_args, frame, value)
            text = {
                 return m_util.html.poe_color('unique', value)
                name = 'row',
            end,
                 field = 'stat_text',
        },
                type = 'Wikitext',
        -- Fields only:
                wikitext = i18n.character_shared_stats.text,
        id = {
                func = function(tpl_args, frame, value)
            name = nil,
                    return m_game.constants.characters.shared_stats[value].text
            field = 'id',
                end,
            type = 'Integer',
            },
            wikitext = i18n.character_class.id,
            value = {
            func = function(tpl_args, frame)
                name = 'row',
                return m_game.constants.characters[tpl_args.name].id
                 field = 'value',
            end,
                type = 'Integer',
        },
                wikitext = i18n.character_shared_stats.value,
        str_id = {
                func = function(tpl_args, frame, value)
            name = nil,
                    return m_game.constants.characters.shared_stats[value].value
            field = 'str_id',
                end,
            type = 'String',
            },
            wikitext = i18n.character_class.str_id,
            func = function(tpl_args, frame)
                 return m_game.constants.characters[tpl_args.name].str_id
            end,
        },
        str = {
            name = nil,
            field = 'strength',
            type = 'String',
            wikitext = i18n.character_class.str,
            func = function(tpl_args, frame)
                return m_game.constants.characters[tpl_args.name].str
            end,
        },
        dex = {
            name = nil,
            field = 'dexterity',
            type = 'String',
            wikitext = i18n.character_class.dex,
            func = function(tpl_args, frame)
                 return m_game.constants.characters[tpl_args.name].dex
            end,
        },
        int = {
            name = nil,
            field = 'intelligence',
            type = 'String',
            wikitext = i18n.character_class.int,
            func = function(tpl_args, frame)
                return m_game.constants.characters[tpl_args.name].int
            end,
         },
         },
     },
     },
}
}


-- Declare cargo table:
tables.character_classes_test = {
p.declare_character_shared_stats = m_util.cargo.declare_factory{
    table = 'character_classes_test',
     data=character_shared_stats_map.main,
    order = {},
    parse_order = {'flavour_text_author'},
     fields = {
        flavour_text_author = {
            name = nil,
            field = 'flavour_text_author',
            type = 'String',
            func = function(tpl_args, frame, value)
                return 'John (JD) Doe'
            end,
        },
    },
}
}


-- Attach cargo table:
p.attach_character_shared_stats = m_util.cargo.attach_factory{
    data=character_shared_stats_map.main,
}


function p.character_shared_stats(frame)
tables.character_classes_test2 = {
    --[[
     table = 'character_classes_test2',
    Displays a infobox and stores cargo data for characters shared stats
     order = {},
   
    parse_order = {'flavour_text_author'},
    Examples:
    fields = {
    = p.character_shared_stats{
        flavour_text_author = {
     }
            name = nil,
    ]]
            field = 'flavour_text_author',
   
            type = 'String',
    -- Get template args:
             func = function(tpl_args, frame, value)
    local tpl_args = getArgs(frame, {parentFirst = true})
                return 'Jane Smith'
    local frame = m_util.misc.get_frame(frame)
             end,
   
    -- Parse character map:
    local map = character_shared_stats_map
   
    -- Store cargo fields:
    for i,v in ipairs(m_game.constants.characters.shared_stats) do
        tpl_args.row = i
        local parsed_map = h.parse_map(tpl_args, frame, map)
        tpl_args = parsed_map.tpl_args
        local cargo_data = parsed_map.cargo_data
        m_util.cargo.store(frame, cargo_data)
    end
   
    -- Main sections, loop through
    local tbl = mw.html.create('table')
    for _, key in ipairs(map.main.order) do
        local data = map.main.fields[key]
       
        if data.display == nil then
            text = tpl_args[key]
        else
            text = data.display(tpl_args, frame, tpl_args[key])
        end
       
        if text ~= nil then         
            tbl
                :tag('tr')
                    :tag('th')
                        :wikitext(data.wikitext)
                        :done()
                    :tag('td')
                        :wikitext(text)
                        :done()
                    :done()
        elseif text then
            tbl
                :tag('tr')
                    :tag('td')
                        -- :attr('colspan', '2')
                        :wikitext(text)
                        :done()
                    :done()
        end
    end
   
    -- Output Infocard
local infocard_args = {
['class'] = 'character_shared_stats',
['header'] = 'Character',
['subheader'] = nil,
[1] = '[[File:Character shared_stats.png|250px]]',
         
[2] = tostring(tbl),
    }
   
    -- Add categories:
    local cats = {
        'Data pages'
    }
   
     return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
end
 
-- ---------------------------------------------------------------------
-- Template: Character class
-- ---------------------------------------------------------------------
local character_map = {
    main = {
        table = 'character_classes',
        order = {'flavour_text'},
        parse_order = {'name', 'flavour_text', 'id'},
        fields = {
            -- Header:
            name = {
                name = 'name',
                field = 'name',
                type = 'String',
                wikitext = i18n.character_class.name,
             },
            -- Main text:
            flavour_text = {
                name = 'flavour_text',
                field = 'flavour_text',
                type = 'String',
                display = function(tpl_args, frame, value)
                    return m_util.html.poe_color('unique', value)
                end,
            },
            -- Fields only:
             id = {
                name = nil,
                field = 'id',
                type = 'String',
                wikitext = i18n.character_class.id,
                func = function(tpl_args, frame)
                    return m_game.constants.characters[tpl_args.name].id
                end,
            },
         },
         },
     },
     },
Line 740: Line 395:


-- Declare cargo table:
-- Declare cargo table:
p.declare_character_classes = m_util.cargo.declare_factory{data=character_map.main}
p.declare_character_classes = m_cargo.declare_factory{data=tables.character_classes}
 
-- Attach cargo table:
p.attach_character_classes = m_util.cargo.attach_factory{data=character_map.main}
 


function p.character_class(frame)
function p.character_class(frame)
     --[[
     --[[
     Displays a infobox and stores cargo data for character classes.
     Displays a infobox and stores cargo data for character classes.
   
 
     Examples:
     Examples:
     = p.character_class{
     = p.character_class{
Line 756: Line 407:
     }
     }
     ]]
     ]]
   
 
   
 
     -- Get template args:
     -- Get template args:
     local tpl_args = getArgs(frame, {parentFirst = true})
     local tpl_args = getArgs(frame, {parentFirst = true})
     local frame = m_util.misc.get_frame(frame)
     local frame = m_util.misc.get_frame(frame)
   
 
     -- Parse character map:
     -- Parse character map:
    local map = character_map
     local parsed_map = h.parse_map(tpl_args, frame, tables.character_classes)
     local parsed_map = h.parse_map(tpl_args, frame, map)
     tpl_args = parsed_map.tpl_args
     tpl_args = parsed_map.tpl_args
     local cargo_data = parsed_map.cargo_data
     local cargo_data = parsed_map.cargo_data
   
 
     -- Store cargo fields:
     -- Store cargo fields:
     m_util.cargo.store(frame, cargo_data)
     m_cargo.store(cargo_data)
 
     -- Main sections, loop through
     -- Main sections, loop through
     local tbl = mw.html.create('table')
     local tbl = mw.html.create('table')
     for _, key in ipairs(map.main.order) do
     for _, key in ipairs(tables.character_classes.order) do
         local data = map.main.fields[key]
         local data = tables.character_classes.fields[key]
       
local text = nil
         if data.display == nil then
         if data.display == nil then
             text = tpl_args[key]
             text = tpl_args[key]
Line 781: Line 431:
             text = data.display(tpl_args, frame, tpl_args[key])
             text = data.display(tpl_args, frame, tpl_args[key])
         end
         end
       
 
         if text ~= nil then          
         if text ~= nil then
             tbl
             tbl
                 :tag('tr')
                 :tag('tr')
Line 802: Line 452:
         end
         end
     end
     end
   
 
     -- Output Infocard
     -- Output Infocard
local infocard_args = {
    local infocard_args = {
['class'] = 'character_class',
        ['class'] = 'character_class',
['header'] = tpl_args.name,
        ['header'] = tpl_args.name,
['subheader'] = nil,
        ['subheader'] = nil,
[1] = string.format(
        [1] = string.format(
             '[[File:%s character class.png|250px]]',
             '[[File:%s character class.png|250px]]',
             tpl_args.name
             tpl_args.name
         ),
         ),
[2] = tostring(tbl),
        [2] = tostring(tbl),
     }
     }
   
 
     -- Add categories:
     -- Add categories:
     local cats = {
     local cats = {
         'Character Classes'
         'Character classes'
     }
     }
   
 
     return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
     return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
end
end
Line 827: Line 477:
-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------


local ascendancy_map = {
tables.ascendancy_classes = {
     main = {
     table = 'ascendancy_classes',
        table = 'ascendancy_classes',
    order = {'flavour_text'},
        order = {'flavour_text'},
    parse_order = {'name', 'character', 'flavour_text', 'id', 'character_id'},
        parse_order = {'name', 'character', 'flavour_text', 'id', 'character_id'},
    fields = {
        fields = {
        -- Header:
            -- Header:
        name = {
            name = {
            name = 'name',
                name = 'name',
            field = 'name',
                field = 'name',
            type = 'String',
                type = 'String',
            wikitext = i18n.ascendancy_class.name,
                wikitext = i18n.ascendancy_class.name,
        },
            },
        -- Subheader:
            -- Subheader:
        character = {
            character = {
            name = nil,
                name = nil,
            field = 'character_class',
                field = 'character',
            type = 'String',
                type = 'String',
            wikitext = i18n.ascendancy_class.character,
                wikitext = i18n.ascendancy_class.character,
            func = function(tpl_args, frame, value)
                func = function(tpl_args, frame, value)
                local id = m_game.constants.ascendancy[tpl_args.name].id
                    local id = m_game.constants.ascendancy[tpl_args.name].id
                local character_id = m_game.constants.ascendancy[tpl_args.name].character
                    local character_id = m_game.constants.ascendancy[tpl_args.name].character
 
                   
                local character
                    local character
                for i,v in pairs(m_game.constants.characters) do
                    for i,v in pairs(m_game.constants.characters) do
                    if v.id == character_id then
                        if v.id == character_id then  
                        character = i
                            character = i
                        break
                            break
                        end
                     end
                     end
                   
                end
                    return character  
 
                end,
                return character
            },
            end,
            -- Main text:
        },
            flavour_text = {
        -- Main text:
                name = 'flavour_text',
        flavour_text = {
                field = 'flavour_text',
            name = 'flavour_text',
                type = 'String',
            field = 'flavour_text',
                display = function(tpl_args, frame, value)
            type = 'String',
                    return m_util.html.poe_color('unique', value)
            display = function(tpl_args, frame, value)
                end,
                return m_util.html.poe_color('unique', value)
            },
            end,
            -- Fields only:
        },
            id = {
        -- Fields only:
                name = nil,
        id = {
                field = 'id',
            name = nil,
                type = 'Integer',
            field = 'id',
                wikitext = i18n.ascendancy_class.id,
            type = 'Integer',
                func = function(tpl_args, frame, value)
            wikitext = i18n.ascendancy_class.id,
                    return m_game.constants.ascendancy[tpl_args.name].id
            func = function(tpl_args, frame, value)
                end,
                return m_game.constants.ascendancy[tpl_args.name].id
            },
            end,
            character_id = {
        },
                name = nil,
        character_id = {
                field = 'character_id',
            name = nil,
                type = 'Integer',
            field = 'character_id',
                wikitext = i18n.ascendancy_class.character_id,
            type = 'Integer',
                func = function(tpl_args, frame, value)
            wikitext = i18n.ascendancy_class.character_id,
                    return m_game.constants.ascendancy[tpl_args.name].character
            func = function(tpl_args, frame, value)
                end,
                return m_game.constants.ascendancy[tpl_args.name].character
            },
            end,
         },
         },
     },
     },
Line 894: Line 542:


-- Declare cargo table:
-- Declare cargo table:
p.declare_ascendancy_classes = m_util.cargo.declare_factory{data=ascendancy_map.main}
p.declare_ascendancy_classes = m_cargo.declare_factory{data=tables.ascendancy_classes}
 
-- Attach cargo table:
p.attach_ascendancy_classes = m_util.cargo.attach_factory{data=ascendancy_map.main}
 


function p.ascendancy_class (frame)
function p.ascendancy_class (frame)
     --[[
     --[[
     Displays a infobox and stores cargo data for ascendancy classes.
     Displays a infobox and stores cargo data for ascendancy classes.
   
 
     Examples:
     Examples:
     = p.ascendancy_class{
     = p.ascendancy_class{
Line 910: Line 554:
     }
     }
     ]]
     ]]
   
 
   
 
     -- Get template args:
     -- Get template args:
     local tpl_args = getArgs(frame, {parentFirst = true})
     local tpl_args = getArgs(frame, {parentFirst = true})
     local frame = m_util.misc.get_frame(frame)
     local frame = m_util.misc.get_frame(frame)
   
 
     -- Parse ascendancy map:
     -- Parse ascendancy map:
    local map = ascendancy_map
     local parsed_map = h.parse_map(tpl_args, frame, tables.ascendancy_classes)
     local parsed_map = h.parse_map(tpl_args, frame, map)
     tpl_args = parsed_map.tpl_args
     tpl_args = parsed_map.tpl_args
     local cargo_data = parsed_map.cargo_data
     local cargo_data = parsed_map.cargo_data
   
 
     -- Store cargo fields:
     -- Store cargo fields:
     m_util.cargo.store(frame, cargo_data)
     m_cargo.store(cargo_data)
 
     -- Main sections, loop through
     -- Main sections, loop through
     local tbl = mw.html.create('table')
     local tbl = mw.html.create('table')
     for _, key in ipairs(map.main.order) do
    local text = nil
         local data = map.main.fields[key]
     for _, key in ipairs(tables.ascendancy_classes.order) do
       
         local data = tables.ascendancy_classes.fields[key]
 
         if data.display == nil then
         if data.display == nil then
             text = tpl_args[key]
             text = tpl_args[key]
Line 935: Line 579:
             text = data.display(tpl_args, frame, tpl_args[key])
             text = data.display(tpl_args, frame, tpl_args[key])
         end
         end
       
 
         if text ~= nil then          
         if text ~= nil then
             tbl
             tbl
                 :tag('tr')
                 :tag('tr')
Line 956: Line 600:
         end
         end
     end
     end
   
 
     -- Output Infocard
     -- Output Infocard
local infocard_args = {
    local infocard_args = {
['class'] = 'ascendancy_class',
        ['class'] = 'ascendancy_class',
['header'] = tpl_args.name,
        ['header'] = tpl_args.name,
['subheader'] = string.format('[[%s]]', tpl_args.character),
        ['subheader'] = string.format('[[%s]]', tpl_args.character),
[1] = string.format(
        [1] = string.format(
             '[[File:%s ascendancy class.png|250px]]',
             '[[File:%s ascendancy class.png|250px]]',
             tpl_args.name
             tpl_args.name
         ),
         ),
[2] = tostring(tbl),
        [2] = tostring(tbl),
     }
     }
   
 
     -- Add categories:
     -- Add categories:
     local cats = {
     local cats = {
         'Ascendancy classes',  
         'Ascendancy classes',
         tpl_args.character .. ' ascendancy classes',
         tpl_args.character .. ' ascendancy classes',
     }
     }
   
 
     return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
     return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
end
end
Line 984: Line 628:
-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------


local event_map = {
tables.events = {
     main = {
     table = 'events',
        table = 'events',
    order = {'release_version', 'release_date', 'end_date', 'number_of_events', 'rewards', 'prize', 'links'},
        order = {'release_version', 'release_date', 'end_date', 'number_of_events', 'rewards', 'price', 'links'},
    parse_order = {'id', 'name', 'short_name', 'type', 'ordinal', 'standard', 'hardcore', 'release_version', 'release_date', 'end_date', 'number_of_events', 'rewards', 'prize', 'links'},
        parse_order = {'id', 'name', 'short_name', 'type', 'ordinal', 'standard', 'hardcore', 'release_version', 'release_date', 'end_date', 'number_of_events', 'rewards', 'price', 'links'},
    fields = {
        fields = {
        -- Header:
            -- Header:
        name = {
            name = {
            name = 'name',
                name = 'name',
            field = 'name',
                field = 'name',
            type = 'String',
                type = 'String',
            wikitext = i18n.event.name,
                wikitext = i18n.event.name,
        },
            },    
        -- Subheader:
            -- Subheader:
        type = {
             type = {
            name = 'type',
                 name = 'type',
            field = 'type',
                 field = 'type',
             type = 'String',
                 type = 'String',
            wikitext = i18n.event.type,
                 wikitext = i18n.event.type,
            func = function(tpl_args, frame, value)
                 func = function(tpl_args, frame, value)
                local type_tbl = {
                     local type_tbl = {
                    challenge = i18n.event.type_challenge,
                         challenge = i18n.event.type_challenge,
                    expansion = i18n.event.type_expansion,
                         expansion = i18n.event.type_expansion,
                    pvp = i18n.event.type_pvp,
                         pvp = i18n.event.type_pvp,
                    race = i18n.event.type_race,
                         race = i18n.event.type_race,
                 }
                return type_tbl[value]
            end,
        },
        -- Main text:
        release_version = {
            name = 'release_version',
            field = 'release_version',
            type = 'String',
            wikitext = i18n.event.release_version,
            display = function(tpl_args, frame, value)
                if value ~= nil then
                    return string.format('[[Version %s|%s]]', value, value)
                 end
            end,
        },
        release_date = {
            name = 'release_date',
            field = 'release_date',
            type = 'Datetime',
            wikitext = i18n.event.release_date,
            cargo_func = function(tpl_args, frame, value)
                 return h.date(value, {format='cargo'})
            end,
            display = function(tpl_args, frame, value)
                local out
                if value ~= nil then
                    out = string.format(
                        '%s %s',
                        h.date(value),
                        h.timezone(value)
                    )
                end
 
                return out
            end,
        },
        end_date = {
            name = 'end_date',
            field = 'end_date',
            type = 'Datetime',
            wikitext = i18n.event.end_date,
            cargo_func = function(tpl_args, frame, value)
                return h.date(value, {format='cargo'})
            end,
            display = function(tpl_args, frame, value)
                local out
                if value ~= nil then
                    out = string.format(
                        '%s %s',
                        h.date(value),
                        h.timezone(value)
                    )
                end
 
                return out
            end,
        },
        standard = {
            name = 'standard',
            field = 'is_standard',
            type = 'Boolean',
            wikitext = i18n.event.standard,
            func = function(tpl_args, frame, value)
                local bool_tbl = {
                    ['false'] = 0,
                    ['true'] = 1,
                }
                return bool_tbl[string.lower(value or '')]
            end,
        },
        hardcore = {
            name = 'hardcore',
            field = 'is_hardcore',
            type = 'Boolean',
            wikitext = i18n.event.hardcore,
            func = function(tpl_args, frame, value)
                local bool_tbl = {
                    ['false'] = 0,
                    ['true'] = 1,
                 }
                return bool_tbl[string.lower(value or '')]
            end,
 
        },
        number_of_events = {
            name = 'number_of_events',
            field = 'number_of_events',
            type = 'Integer',
            wikitext = i18n.event.number_of_events,
        },
        rewards = {
            name = 'rewards',
            field = 'rewards',
            type = 'Wikitext',
            wikitext = 'Rewards',
            display = function(tpl_args, frame, value)
                local out
                 if value ~= nil then
                    out = string.format(
                        '<div style="text-align: right;">%s</div>',
                        value
                    )
                end
                return out
            end,
        },
        prize = {
            name = 'prize',
            field = 'prize',
            type = 'Wikitext',
            wikitext = i18n.event.prize,
        },
        links = {
            name = 'links',
            field = 'links',
            type = 'Wikitext',
            wikitext = i18n.event.links,
        },
 
        -- Field calculations:
        id = {
            name = 'id',
            field = 'id',
            type = 'List (, ) of String',
            wikitext = i18n.event.id,
        },
        short_name = {
            name = nil,
            field = 'short_name',
            type = 'String',
            wikitext = i18n.event.short_name,
            func = function(tpl_args, frame)
                local out = {}
                for i,v in pairs(tpl_args) do
                     local match_tbl = {
                         challenge = i18n.event.match_challenge,
                         expansion = i18n.event.match_expansion,
                         pvp = i18n.event.match_pvp,
                         race = i18n.event.match_race,
                     }
                     }
                    return type_tbl[value]
                     for ii,vv in pairs(match_tbl) do
                end,
                        if v==ii then
            },           
                            out[#out+1] = tpl_args['name']:lower():gsub(vv, ''):gsub('^%l', string.upper)
            -- Main text:
                            break
release_version = {
name = 'release_version',
                field = 'release_version',
                type = 'String',
                wikitext = i18n.event.release_version,
                display = function(tpl_args, frame, value)
                    if value ~= nil then
                        return string.format('[[Version %s|%s]]', value, value)
                    end
                end,
},
release_date = {
name = 'release_date',
                field = 'release_date',
                type = 'Datetime',
                wikitext = i18n.event.release_date,
                cargo_func = function(tpl_args, frame, value)
                    return h.date(value, {format='cargo'})
                end,
                display = function(tpl_args, frame, value)
                    local out
                    if value ~= nil then
                        out = string.format(
                            '%s %s',
                            h.date(value),
                            h.timezone(value)
                        )
                    end
                   
                    return out
                end,
},
end_date = {
name = 'end_date',
                field = 'release_date',
                type = 'Datetime',
                wikitext = i18n.event.end_date,
                cargo_func = function(tpl_args, frame, value)
                    return h.date(value, {format='cargo'})
                end,
                display = function(tpl_args, frame, value)
                    local out
                    if value ~= nil then
                        out = string.format(
                            '%s %s',
                            h.date(value),
                            h.timezone(value)
                        )
                    end
                   
                    return out
                end,
},
standard = {
name = 'standard',
                field = 'is_standard',
                type = 'Boolean',
                wikitext = i18n.event.standard,
                func = function(tpl_args, frame, value)
                    local bool_tbl = {
                        ['false'] = 0,
                        ['true'] = 1,
                    }
                    return bool_tbl[string.lower(value or '')]
                end,
},
hardcore = {
name = 'hardcore',
                field = 'is_hardcore',
                type = 'Boolean',
                wikitext = i18n.event.hardcore,
                func = function(tpl_args, frame, value)
                    local bool_tbl = {
                        ['false'] = 0,
                        ['true'] = 1,
                    }
                    return bool_tbl[string.lower(value or '')]
                end,
               
            },           
number_of_events = {
name = 'number_of_events',
                field = 'number_of_events',
                type = 'Integer',
                wikitext = i18n.event.number_of_events,
},
rewards = {
name = 'rewards',
                field = 'rewards',
                type = 'Wikitext',
                wikitext = 'Rewards',
                display = function(tpl_args, frame, value)
                    local out
                    if value ~= nil then
                        out = string.format(
                            '<div style="text-align: right;">%s</div>',
                            value
                        )
                    end
                    return out
                end,
},
price = {
name = 'price',
                field = 'price',
                type = 'Wikitext',
                wikitext = i18n.event.price,
},
links = {
name = 'links',
                field = 'links',
                type = 'Wikitext',
                wikitext = i18n.event.links,
},
           
            -- Field calculations:
            id = {
                name = 'id',
                field = 'id',
                type = 'List (, ) of String',
                wikitext = i18n.event.id,
            },
            short_name = {
                name = nil,
                field = 'short_name',
                type = 'String',
                wikitext = i18n.event.short_name,
                func = function(tpl_args, frame)
                    local out = {}
                     for i,v in pairs(tpl_args) do
                        local match_tbl = {
                            challenge = i18n.event.match_challenge,
                            expansion = i18n.event.match_expansion,
                            pvp = i18n.event.match_pvp,
                            race = i18n.event.match_race,
                        }
                        for ii,vv in pairs(match_tbl) do
                            if v==ii then
                                out[#out+1] = tpl_args['name']:lower():gsub(vv, ''):gsub('^%l', string.upper)
                                break
                            end
                         end
                         end
                     end
                     end
                    return table.concat(out, ', ')
                end
                end,
                return table.concat(out, ', ')
            },
            end,
            ordinal = {
        },
                name = nil,
        ordinal = {
                field = 'ordinal',
            name = nil,
                type = 'String',
            field = 'ordinal',
                wikitext = i18n.event.ordinal,  
            type = 'Integer',
                func = function(tpl_args, frame)
            wikitext = i18n.event.ordinal,
                    tpl_args.tables = 'events'
            func = function(tpl_args, frame)
                    local count = string.format(
                tpl_args.tables = 'events'
                        'COUNT(DISTINCT %s._pageName)',  
                local count = string.format(
                        tpl_args.tables
                    'COUNT(DISTINCT %s._pageName)',
                    )
                    tpl_args.tables
                    tpl_args.fields = count
                )
                    tpl_args.q_where = string.format(
                tpl_args.fields = count
                        '%s.type = "%s" AND %s.release_date < "%s"',  
                tpl_args.q_where = string.format(
                        tpl_args.tables,
                    '%s.type = "%s" AND %s.release_date < "%s"',
                        tpl_args.type or '',  
                    tpl_args.tables,
                        tpl_args.tables,
                    tpl_args.type or '',
                        tpl_args.release_date or ''
                    tpl_args.tables,
                    )
                    tpl_args.release_date or ''
                    local results = h.cargo_query(tpl_args)
                )
                   
                local results = h.cargo_query(tpl_args)
                    if #results > 0 then  
 
                        return results[1][count]
                local out = 1
                    else
                if #results > 0 then
                        return nil
                    out = out + results[1][count]
                    end
                end
                 end,
 
             },
                 return out
             end,
         },
         },
     },
     },
Line 1,193: Line 836:


-- Declare cargo table:
-- Declare cargo table:
p.declare_events = m_util.cargo.declare_factory{data=event_map.main}
p.declare_events = m_cargo.declare_factory{data=tables.events}
 
-- Attach cargo table:
p.attach_events = m_util.cargo.attach_factory{data=event_map.main}
 


function p.event_box(tpl_args, frame, map)
function p.event_box(tpl_args, frame)
     -- Main sections, loop through
     -- Main sections, loop through
     local tbl = mw.html.create('table')
     local tbl = mw.html.create('table')
     for _, key in ipairs(map.main.order) do
     for _, key in ipairs(tables.events.order) do
         local data = map.main.fields[key]
         local data = tables.events.fields[key]
       
local text = nil
         if data.display == nil then
         if data.display == nil then
             text = tpl_args[key]
             text = tpl_args[key]
Line 1,210: Line 850:
             text = data.display(tpl_args, frame, tpl_args[key])
             text = data.display(tpl_args, frame, tpl_args[key])
         end
         end
       
 
         if text ~= nil then          
         if text ~= nil then
             tbl
             tbl
                 :tag('tr')
                 :tag('tr')
Line 1,231: Line 871:
         end
         end
     end
     end
   
 
     -- Output Infocard
     -- Output Infocard
local infocard_args = {
    local infocard_args = {
['class'] = 'event',
        ['class'] = 'event',
['header'] = tpl_args.name,
        ['header'] = tpl_args.name,
['subheader'] = tpl_args.type,
        ['subheader'] = tpl_args.type,
[1] = string.format(
        [1] = string.format(
             '[[File:%s|250px]]',  
             '[[File:%s|250px]]',
             tpl_args.image or string.format('%s_logo.png', tpl_args.name)
             tpl_args.image or string.format('%s_logo.png', tpl_args.name)
         ),
         ),
[2] = tostring(tbl),
        [2] = tostring(tbl),
     }
     }


Line 1,255: Line 895:
function p.event(frame)
function p.event(frame)
     --[[
     --[[
     Displays a infobox and stores data for various events such as  
     Displays a infobox and stores data for various events such as
     game expansions, leagues, races, pvp etc.
     game expansions, leagues, races, pvp etc.
   
    Examples:


      
     Examples:
 
 
     ]]
     ]]
     -- Get template args:
     -- Get template args:
     local tpl_args = getArgs(frame, {parentFirst = true})
     local tpl_args = getArgs(frame, {parentFirst = true})
     local frame = m_util.misc.get_frame(frame)
     local frame = m_util.misc.get_frame(frame)
 
     -- Parse event_map:
     -- Parse event_map:
     local parsed_map = h.parse_map(tpl_args, frame, event_map)
     local parsed_map = h.parse_map(tpl_args, frame, tables.events)
     tpl_args = parsed_map.tpl_args
     tpl_args = parsed_map.tpl_args
     local cargo_data = parsed_map.cargo_data
     local cargo_data = parsed_map.cargo_data
   
 
     -- Store cargo fields:
     -- Store cargo fields:
     m_util.cargo.store(frame, cargo_data)  
     m_cargo.store(cargo_data)
   
 
     -- Display infobox:
     -- Display infobox:
     local out = p.event_box(tpl_args, frame, event_map)
     local out = p.event_box(tpl_args, frame)
   
 
     -- Add categories:
     -- Add categories:
     local cats = {
     local cats = {
tpl_args.type .. 's',
        tpl_args.type .. 's',
     }
     }
   
 
     return out .. m_util.misc.add_category(cats)
     return out .. m_util.misc.add_category(cats)
end
end


-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------


return p
return p

Latest revision as of 04:00, 9 June 2022

Module documentation[view] [edit] [history] [purge]


Lua logo

This module depends on the following other modules:

The data tables module creates infoboxes and stores cargo data.

Subpages

--[[
    Module for data tables

    Attempts to create advanced infoboxes in a standardized way.
]]

local getArgs = require('Module:Arguments').getArgs
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
local m_game = require('Module:Game')
local f_infocard = require('Module:Infocard')._main
local mw_language = mw.getLanguage('en')

local p = {}

-- Internationalization of public strings:
local i18n = {
    character_class = {
        name = 'Name',
        id = 'Id',
    },
    generic_stats = {
        name = 'Name',
        id = 'Id',
        str_id = 'Str_id',
        str = 'Strength',
        dex = 'Dexterity',
        int = 'Intelligence',
        stat_text = 'Text',
        value = 'Value',
    },
    ascendancy_class = {
        name = 'Name',
        id = 'Id',
        flavour_text = 'Flavour text',
        character_id = 'Character id',
        character = 'Character',
    },
    event = {
        name = 'Name',
        id = 'Id',
        type = 'Type',
        type_challenge = 'Challenge league',
        type_expansion = 'Expansion',
        type_pvp = 'PvP season',
        type_race = 'Race season',
        release_version = 'Release version',
        release_date = 'Release date',
        end_date = 'End date',
        standard = 'Standard',
        hardcore = 'Hardcore',
        ordinal = 'Ordinal number',
        short_name = 'Short name',
        match_challenge = 'league',
        match_expansion = 'Please, do not match this.',
        match_pvp = 'pvp season',
        match_race = 'race season',
        number_of_events = 'Number of events',
        prize = 'Prize',
        rewards = 'Rewards',
        links = 'Links',
    },
}

-- ---------------------------------------------------------------------
-- Utility / Helper functions
-- ---------------------------------------------------------------------
local h = {}

function h.date(value, args)
    --[[
    Format dates in correct and useable form.

    Parameters
    ----------
    value : String, required
        Date
    args : Table
        Table with extra formatting args.

    To do:
    Remove hours if it isn't specified.
    ]]

    local args = args or {}

    -- List of allowed extra arguments:
    local arg_list = {
        format = {
            default = 'Y-m-d H:i:s',
            cargo   = 'Y-m-d H:i:s',
            no_time = 'Y-m-d',
        },
    }

    local date_format = arg_list['format']['default']
    local timestamp = mw_language:formatDate(date_format, value)

    -- If the time is 00:00:00 then assume that the time isn't defined:
    if mw_language:formatDate('H:i:s', timestamp) == '00:00:00' then
        date_format = arg_list['format']['no_time']
    end

    -- Add the extra arguments:
    for i,v in pairs(args) do
        if i == 'format' then
            date_format = arg_list[i][v]
        end
    end

    -- Return the final timestamp format:
    local out
    if value ~= nil then
        out = mw_language:formatDate(date_format, timestamp)
    end

    return out
end

function h.timezone(str)
    --[[
    Check if the string contains Z at the end, if it does it implies
    the time is in UTC and then return UTC.
    ]]

    local out = ''
    if str ~= nil and str:sub(-1,-1) == 'Z' then
        out = 'UTC'
    end

    return out
end

function h.cargo_query(tpl_args)
    --[[
    Returns a Cargo query of all the results.

    tpl_args should include these keys:
    tpl_args.tables
    tpl_args.fields
    tpl_args.q_*

    ]]

    local tables = m_util.string.split(tpl_args.tables, ', ')
    local fields = m_util.string.split(tpl_args.fields, ', ')

    -- Parse query arguments
    local query = {
    }
    for key, value in pairs(tpl_args) do
        if string.sub(key, 0, 2) == 'q_' then
            query[string.sub(key, 3)] = value
        end
    end

    -- Query cargo rows:
    local results = m_cargo.query(tables, fields, query)

    return results
end

function h.parse_map(tpl_args, frame, tbldef)
    --[[
        Parse the map

        Input:

    ]]
    local cargo_data = {
        _table = tbldef.table,
    }
    for _, key in pairs(tbldef.parse_order) do
        local data = tbldef.fields[key]
        local value
        if data.func ~= nil then
            if data.name then
                value = data.func(tpl_args, frame, tpl_args[data.name])
            else
                value = data.func(tpl_args, frame)
            end
        else
            value = tpl_args[data.name]
        end

        tpl_args[key] = value

        if data.field ~= nil then
            if data.func_cargo then
                cargo_data[data.field] = data.func_cargo(tpl_args, frame)
            else
                cargo_data[data.field] = value
            end
        end
    end

    local out = {
        tpl_args = tpl_args,
        cargo_data = cargo_data,
    }

    return out
end

h.parse_stat_args = function(tpl_args, args)
    --[[
    Parse template args that starts with stat.+ and return them as a
    array.

    ]]

    out = {}
    for key, value in pairs(tpl_args) do
        if string.sub(key, 0, 4) == 'stat' then
            local n,k = string.match(key, 'stat(%d+)_(.+)')
            n = tostring(n)
            if out[n] == nil then
                out[n] = {}
            end
            if n ~= nil and k ~= nil then
                out[n][k] = value
            else
                error(string.format(
                    'Wrong stat argument format. The template argument "%s" matched "%s" and "%s".',
                    key or 'n/a', n or 'n/a', k or 'n/a'
                    )
                )
            end
        end
    end

    return out
end


-- ---------------------------------------------------------------------
-- Template: Generic stats
-- ---------------------------------------------------------------------

local tables = {
    generic_stats = {
        table = 'generic_stats',
        order = {},
        parse_order = {'name', 'id', 'stat_text', 'value'},
        fields = {
            name = {
                name = 'name',
                field = 'name',
                type = 'String',
                wikitext = i18n.generic_stats.name,
            },
            id = {
                name = 'row',
                field = 'id',
                type = 'String',
                wikitext = i18n.generic_stats.id,
                func = function(tpl_args, frame, value)
                    return tpl_args.stats[value].id
                end,
            },
            stat_text = {
                name = 'row',
                field = 'stat_text',
                type = 'Wikitext',
                wikitext = i18n.generic_stats.stat_text,
                func = function(tpl_args, frame, value)
                    return tpl_args.stats[value].stat_text
                end,
            },
            value = {
                name = 'row',
                field = 'value',
                type = 'Integer',
                wikitext = i18n.generic_stats.value,
                func = function(tpl_args, frame, val)
                    return tpl_args.stats[val].value
                end,
            },
        },
    },
}

-- Declare cargo table:
p.declare_generic_stats = m_cargo.declare_factory{
    data=tables.generic_stats,
}

p.store_data = m_cargo.store_from_lua{tables=tables, module='Data tables'}

-- --------------------------------------------------------------------
-- Template: Character class
-- ---------------------------------------------------------------------
tables.character_classes = {
    table = 'character_classes',
    order = {'flavour_text'},
    parse_order = {'name', 'flavour_text', 'id', 'str_id', 'str', 'dex', 'int'},
    fields = {
        -- Header:
        name = {
            name = 'name',
            field = 'name',
            type = 'String',
            wikitext = i18n.character_class.name,
        },
        -- Main text:
        flavour_text = {
            name = 'flavour_text',
            field = 'flavour_text',
            type = 'String',
            display = function(tpl_args, frame, value)
                return m_util.html.poe_color('unique', value)
            end,
        },
        -- Fields only:
        id = {
            name = nil,
            field = 'id',
            type = 'Integer',
            wikitext = i18n.character_class.id,
            func = function(tpl_args, frame)
                return m_game.constants.characters[tpl_args.name].id
            end,
        },
        str_id = {
            name = nil,
            field = 'str_id',
            type = 'String',
            wikitext = i18n.character_class.str_id,
            func = function(tpl_args, frame)
                return m_game.constants.characters[tpl_args.name].str_id
            end,
        },
        str = {
            name = nil,
            field = 'strength',
            type = 'String',
            wikitext = i18n.character_class.str,
            func = function(tpl_args, frame)
                return m_game.constants.characters[tpl_args.name].str
            end,
        },
        dex = {
            name = nil,
            field = 'dexterity',
            type = 'String',
            wikitext = i18n.character_class.dex,
            func = function(tpl_args, frame)
                return m_game.constants.characters[tpl_args.name].dex
            end,
        },
        int = {
            name = nil,
            field = 'intelligence',
            type = 'String',
            wikitext = i18n.character_class.int,
            func = function(tpl_args, frame)
                return m_game.constants.characters[tpl_args.name].int
            end,
        },
    },
}

tables.character_classes_test = {
    table = 'character_classes_test',
    order = {},
    parse_order = {'flavour_text_author'},
    fields = {
        flavour_text_author = {
            name = nil,
            field = 'flavour_text_author',
            type = 'String',
            func = function(tpl_args, frame, value)
                return 'John (JD) Doe'
            end,
        },
    },
}


tables.character_classes_test2 = {
    table = 'character_classes_test2',
    order = {},
    parse_order = {'flavour_text_author'},
    fields = {
        flavour_text_author = {
            name = nil,
            field = 'flavour_text_author',
            type = 'String',
            func = function(tpl_args, frame, value)
                return 'Jane Smith'
            end,
        },
    },
}

-- Declare cargo table:
p.declare_character_classes = m_cargo.declare_factory{data=tables.character_classes}

function p.character_class(frame)
    --[[
    Displays a infobox and stores cargo data for character classes.

    Examples:
    = p.character_class{
        name='Marauder',
        flavour_text='testing'
    }
    ]]


    -- Get template args:
    local tpl_args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)

    -- Parse character map:
    local parsed_map = h.parse_map(tpl_args, frame, tables.character_classes)
    tpl_args = parsed_map.tpl_args
    local cargo_data = parsed_map.cargo_data

    -- Store cargo fields:
    m_cargo.store(cargo_data)

    -- Main sections, loop through
    local tbl = mw.html.create('table')
    for _, key in ipairs(tables.character_classes.order) do
        local data = tables.character_classes.fields[key]
		local text = nil
        if data.display == nil then
            text = tpl_args[key]
        else
            text = data.display(tpl_args, frame, tpl_args[key])
        end

        if text ~= nil then
            tbl
                :tag('tr')
                    :tag('th')
                        :wikitext(data.wikitext)
                        :done()
                    :tag('td')
                        :wikitext(text)
                        :done()
                    :done()
        elseif text then
            tbl
                :tag('tr')
                    :tag('td')
                        -- :attr('colspan', '2')
                        :wikitext(text)
                        :done()
                    :done()
        end
    end

    -- Output Infocard
    local infocard_args = {
        ['class'] = 'character_class',
        ['header'] = tpl_args.name,
        ['subheader'] = nil,
        [1] = string.format(
            '[[File:%s character class.png|250px]]',
            tpl_args.name
        ),
        [2] = tostring(tbl),
    }

    -- Add categories:
    local cats = {
        'Character classes'
    }

    return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
end

-- ---------------------------------------------------------------------
-- Template: Ascendancy Class
-- ---------------------------------------------------------------------

tables.ascendancy_classes = {
    table = 'ascendancy_classes',
    order = {'flavour_text'},
    parse_order = {'name', 'character', 'flavour_text', 'id', 'character_id'},
    fields = {
        -- Header:
        name = {
            name = 'name',
            field = 'name',
            type = 'String',
            wikitext = i18n.ascendancy_class.name,
        },
        -- Subheader:
        character = {
            name = nil,
            field = 'character_class',
            type = 'String',
            wikitext = i18n.ascendancy_class.character,
            func = function(tpl_args, frame, value)
                local id = m_game.constants.ascendancy[tpl_args.name].id
                local character_id = m_game.constants.ascendancy[tpl_args.name].character

                local character
                for i,v in pairs(m_game.constants.characters) do
                    if v.id == character_id then
                        character = i
                        break
                    end
                end

                return character
            end,
        },
        -- Main text:
        flavour_text = {
            name = 'flavour_text',
            field = 'flavour_text',
            type = 'String',
            display = function(tpl_args, frame, value)
                return m_util.html.poe_color('unique', value)
            end,
        },
        -- Fields only:
        id = {
            name = nil,
            field = 'id',
            type = 'Integer',
            wikitext = i18n.ascendancy_class.id,
            func = function(tpl_args, frame, value)
                return m_game.constants.ascendancy[tpl_args.name].id
            end,
        },
        character_id = {
            name = nil,
            field = 'character_id',
            type = 'Integer',
            wikitext = i18n.ascendancy_class.character_id,
            func = function(tpl_args, frame, value)
                return m_game.constants.ascendancy[tpl_args.name].character
            end,
        },
    },
}

-- Declare cargo table:
p.declare_ascendancy_classes = m_cargo.declare_factory{data=tables.ascendancy_classes}

function p.ascendancy_class (frame)
    --[[
    Displays a infobox and stores cargo data for ascendancy classes.

    Examples:
    = p.ascendancy_class{
        name='Slayer',
        flavour_text='testing'
    }
    ]]


    -- Get template args:
    local tpl_args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)

    -- Parse ascendancy map:
    local parsed_map = h.parse_map(tpl_args, frame, tables.ascendancy_classes)
    tpl_args = parsed_map.tpl_args
    local cargo_data = parsed_map.cargo_data

    -- Store cargo fields:
    m_cargo.store(cargo_data)

    -- Main sections, loop through
    local tbl = mw.html.create('table')
    local text = nil
    for _, key in ipairs(tables.ascendancy_classes.order) do
        local data = tables.ascendancy_classes.fields[key]

        if data.display == nil then
            text = tpl_args[key]
        else
            text = data.display(tpl_args, frame, tpl_args[key])
        end

        if text ~= nil then
            tbl
                :tag('tr')
                    :tag('th')
                        :wikitext(data.wikitext)
                        :done()
                    :tag('td')
                        :wikitext(text)
                        :done()
                    :done()
        elseif text then
            tbl
                :tag('tr')
                    :tag('td')
                        -- :attr('colspan', '2')
                        :wikitext(text)
                        :done()
                    :done()
        end
    end

    -- Output Infocard
    local infocard_args = {
        ['class'] = 'ascendancy_class',
        ['header'] = tpl_args.name,
        ['subheader'] = string.format('[[%s]]', tpl_args.character),
        [1] = string.format(
            '[[File:%s ascendancy class.png|250px]]',
            tpl_args.name
        ),
        [2] = tostring(tbl),
    }

    -- Add categories:
    local cats = {
        'Ascendancy classes',
        tpl_args.character .. ' ascendancy classes',
    }

    return f_infocard(infocard_args) .. m_util.misc.add_category(cats)
end



-- ---------------------------------------------------------------------
-- Template: Event
-- ---------------------------------------------------------------------

tables.events = {
    table = 'events',
    order = {'release_version', 'release_date', 'end_date', 'number_of_events', 'rewards', 'prize', 'links'},
    parse_order = {'id', 'name', 'short_name', 'type', 'ordinal', 'standard', 'hardcore', 'release_version', 'release_date', 'end_date', 'number_of_events', 'rewards', 'prize', 'links'},
    fields = {
        -- Header:
        name = {
            name = 'name',
            field = 'name',
            type = 'String',
            wikitext = i18n.event.name,
        },
        -- Subheader:
        type = {
            name = 'type',
            field = 'type',
            type = 'String',
            wikitext = i18n.event.type,
            func = function(tpl_args, frame, value)
                local type_tbl = {
                    challenge = i18n.event.type_challenge,
                    expansion = i18n.event.type_expansion,
                    pvp = i18n.event.type_pvp,
                    race = i18n.event.type_race,
                }
                return type_tbl[value]
            end,
        },
        -- Main text:
        release_version = {
            name = 'release_version',
            field = 'release_version',
            type = 'String',
            wikitext = i18n.event.release_version,
            display = function(tpl_args, frame, value)
                if value ~= nil then
                    return string.format('[[Version %s|%s]]', value, value)
                end
            end,
        },
        release_date = {
            name = 'release_date',
            field = 'release_date',
            type = 'Datetime',
            wikitext = i18n.event.release_date,
            cargo_func = function(tpl_args, frame, value)
                return h.date(value, {format='cargo'})
            end,
            display = function(tpl_args, frame, value)
                local out
                if value ~= nil then
                    out = string.format(
                        '%s %s',
                        h.date(value),
                        h.timezone(value)
                    )
                end

                return out
            end,
        },
        end_date = {
            name = 'end_date',
            field = 'end_date',
            type = 'Datetime',
            wikitext = i18n.event.end_date,
            cargo_func = function(tpl_args, frame, value)
                return h.date(value, {format='cargo'})
            end,
            display = function(tpl_args, frame, value)
                local out
                if value ~= nil then
                    out = string.format(
                        '%s %s',
                        h.date(value),
                        h.timezone(value)
                    )
                end

                return out
            end,
        },
        standard = {
            name = 'standard',
            field = 'is_standard',
            type = 'Boolean',
            wikitext = i18n.event.standard,
            func = function(tpl_args, frame, value)
                local bool_tbl = {
                    ['false'] = 0,
                    ['true'] = 1,
                }
                return bool_tbl[string.lower(value or '')]
            end,
        },
        hardcore = {
            name = 'hardcore',
            field = 'is_hardcore',
            type = 'Boolean',
            wikitext = i18n.event.hardcore,
            func = function(tpl_args, frame, value)
                local bool_tbl = {
                    ['false'] = 0,
                    ['true'] = 1,
                }
                return bool_tbl[string.lower(value or '')]
            end,

        },
        number_of_events = {
            name = 'number_of_events',
            field = 'number_of_events',
            type = 'Integer',
            wikitext = i18n.event.number_of_events,
        },
        rewards = {
            name = 'rewards',
            field = 'rewards',
            type = 'Wikitext',
            wikitext = 'Rewards',
            display = function(tpl_args, frame, value)
                local out
                if value ~= nil then
                    out = string.format(
                        '<div style="text-align: right;">%s</div>',
                        value
                    )
                end
                return out
            end,
        },
        prize = {
            name = 'prize',
            field = 'prize',
            type = 'Wikitext',
            wikitext = i18n.event.prize,
        },
        links = {
            name = 'links',
            field = 'links',
            type = 'Wikitext',
            wikitext = i18n.event.links,
        },

        -- Field calculations:
        id = {
            name = 'id',
            field = 'id',
            type = 'List (, ) of String',
            wikitext = i18n.event.id,
        },
        short_name = {
            name = nil,
            field = 'short_name',
            type = 'String',
            wikitext = i18n.event.short_name,
            func = function(tpl_args, frame)
                local out = {}
                for i,v in pairs(tpl_args) do
                    local match_tbl = {
                        challenge = i18n.event.match_challenge,
                        expansion = i18n.event.match_expansion,
                        pvp = i18n.event.match_pvp,
                        race = i18n.event.match_race,
                    }
                    for ii,vv in pairs(match_tbl) do
                        if v==ii then
                            out[#out+1] = tpl_args['name']:lower():gsub(vv, ''):gsub('^%l', string.upper)
                            break
                        end
                    end
                end
                return table.concat(out, ', ')
            end,
        },
        ordinal = {
            name = nil,
            field = 'ordinal',
            type = 'Integer',
            wikitext = i18n.event.ordinal,
            func = function(tpl_args, frame)
                tpl_args.tables = 'events'
                local count = string.format(
                    'COUNT(DISTINCT %s._pageName)',
                    tpl_args.tables
                )
                tpl_args.fields = count
                tpl_args.q_where = string.format(
                    '%s.type = "%s" AND %s.release_date < "%s"',
                    tpl_args.tables,
                    tpl_args.type or '',
                    tpl_args.tables,
                    tpl_args.release_date or ''
                )
                local results = h.cargo_query(tpl_args)

                local out = 1
                if #results > 0 then
                    out = out + results[1][count]
                end

                return out
            end,
        },
    },
}

-- Declare cargo table:
p.declare_events = m_cargo.declare_factory{data=tables.events}

function p.event_box(tpl_args, frame)
    -- Main sections, loop through
    local tbl = mw.html.create('table')
    for _, key in ipairs(tables.events.order) do
        local data = tables.events.fields[key]
		
		local text = nil
        if data.display == nil then
            text = tpl_args[key]
        else
            text = data.display(tpl_args, frame, tpl_args[key])
        end

        if text ~= nil then
            tbl
                :tag('tr')
                    :tag('th')
                        :wikitext(data.wikitext)
                        :done()
                    :tag('td')
                        :wikitext(text)
                        :done()
                    :done()
        elseif text then
            tbl
                :tag('tr')
                    :tag('td')
                        -- :attr('colspan', '2')
                        :wikitext(text)
                        :done()
                    :done()
        end
    end

    -- Output Infocard
    local infocard_args = {
        ['class'] = 'event',
        ['header'] = tpl_args.name,
        ['subheader'] = tpl_args.type,
        [1] = string.format(
            '[[File:%s|250px]]',
            tpl_args.image or string.format('%s_logo.png', tpl_args.name)
        ),
        [2] = tostring(tbl),
    }

    return f_infocard(infocard_args)
end

    -- =p.event{name='Ascendancy', type = 'expansion', release_version = '2.2.0', release_date = '2016-03-04'}
    -- =p.event{name='Winterheart race season', type='race', release_version = '2.3.0', release_date='2016-01-29', end_date='2016-08-29T22:00:00Z', number_of_events='155', rewards="[[Asphyxia's Wrath]] <br> [[Sapphire Ring]] <br> [[The Whispering Ice]] <br> [[Dyadian Dawn]] <br> [[Call of the Brotherhood]] <br> [[Winterheart]]", prize="[[Demigod's Dominance]]", links='[http://www.pathofexile.com/seasons Schedule and overview]'  }
    -- c=p.event{name='PvP season 2', type='pvp', release_date='2015-02-15', end_date='2015-03-16', rewards="[[Wanderlust]] <br> [[Coral Ring]] <br> [[Geofri's Baptism]] <br> [[Kikazaru]] <br> [[Meginord's Girdle]] <br> [[Atziri's Foible]]", prize='[[Talisman of the Victor]]', links='[http://www.pathofexile.com/seasons/pvp/season/EUPvPSeason2 EU PvP Ladder] <br> [http://www.pathofexile.com/seasons/pvp/season/USPvPSeason2 US PvP Ladder]'  }
    -- =p.event{name='Perandus league', type='challenge ', release_version = '2.2.0', release_date='2016-03-04', end_date='2016-05-30', standard = 'True', hardcore = 'True'}


function p.event(frame)
    --[[
    Displays a infobox and stores data for various events such as
    game expansions, leagues, races, pvp etc.

    Examples:


    ]]
    -- Get template args:
    local tpl_args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)

    -- Parse event_map:
    local parsed_map = h.parse_map(tpl_args, frame, tables.events)
    tpl_args = parsed_map.tpl_args
    local cargo_data = parsed_map.cargo_data

    -- Store cargo fields:
    m_cargo.store(cargo_data)

    -- Display infobox:
    local out = p.event_box(tpl_args, frame)

    -- Add categories:
    local cats = {
        tpl_args.type .. 's',
    }

    return out .. m_util.misc.add_category(cats)
end

-- ---------------------------------------------------------------------

return p