Module:Data tables: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
>Illviljan
(Testing attaching to multiple cargo tables at the same time again. Multiple attaches can't be on the same page, so let's try to transclude it from another page instead using includeonly.)
No edit summary
 
(18 intermediate revisions by 5 users not shown)
Line 1: Line 1:
--[[
--[[
     Module for data tables
     Module for data tables
   
 
     Attempts to create advanced infoboxes in a standardized way.
     Attempts to create advanced infoboxes in a standardized way.
]]
]]
Line 7: Line 7:
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 22: Line 23:
         name = 'Name',
         name = 'Name',
         id = 'Id',
         id = 'Id',
        str_id = 'Str_id',
        str = 'Strength',
        dex = 'Dexterity',
        int = 'Intelligence',
         stat_text = 'Text',
         stat_text = 'Text',
         value = 'Value',
         value = 'Value',
Line 52: 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',
Line 66: Line 71:
     --[[
     --[[
     Format dates in correct and useable form.
     Format dates in correct and useable form.
   
 
     Parameters
     Parameters
     ----------
     ----------
Line 73: Line 78:
     args : Table
     args : Table
         Table with extra formatting args.
         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 = {
Line 88: Line 93:
         },
         },
     }
     }
   
 
     local date_format = arg_list['format']['default']
     local date_format = arg_list['format']['default']
     local timestamp = mw_language:formatDate(date_format, value)
     local timestamp = mw_language:formatDate(date_format, value)
   
 
     -- If the time is 00:00:00 then assume that the time isn't defined:
     -- 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  
     if mw_language:formatDate('H:i:s', timestamp) == '00:00:00' then
         date_format = arg_list['format']['no_time']
         date_format = arg_list['format']['no_time']
     end
     end
   
 
     -- Add the extra arguments:
     -- 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:
     -- Return the final timestamp format:
     local out
     local out
Line 109: Line 114:
         out = mw_language:formatDate(date_format, timestamp)
         out = mw_language:formatDate(date_format, timestamp)
     end
     end
   
 
     return out
     return out
end
end
Line 115: 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.
     ]]
     ]]
   
 
     local out = ''
     local out = ''
if str ~= nil and str:sub(-1,-1) == 'Z' then
    if str ~= nil and str:sub(-1,-1) == 'Z' then
out = 'UTC'
        out = 'UTC'
end
    end
   
 
     return out
     return out
end
end
Line 130: 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 178: Line 183:
             value = tpl_args[data.name]
             value = tpl_args[data.name]
         end
         end
       
 
         tpl_args[key] = value
         tpl_args[key] = value


Line 189: 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 200: 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
Line 210: Line 215:
             local n,k = string.match(key, 'stat(%d+)_(.+)')
             local n,k = string.match(key, 'stat(%d+)_(.+)')
             n = tostring(n)
             n = tostring(n)
             if out[n] == nil then  
             if out[n] == nil then
                 out[n] = {}  
                 out[n] = {}
             end
             end
             if n ~= nil and k ~= nil then  
             if n ~= nil and k ~= nil then
                 out[n][k] = value
                 out[n][k] = value
             else  
             else
                 error(string.format(
                 error(string.format(
                     'Wrong stat argument format. The template argument "%s" matched "%s" and "%s".',  
                     'Wrong stat argument format. The template argument "%s" matched "%s" and "%s".',
                     key or 'n/a', n or 'n/a', k or 'n/a'
                     key or 'n/a', n or 'n/a', k or 'n/a'
                     )
                     )
Line 233: Line 238:
-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------


local generic_stats_map = {
local tables = {
     main = {
     generic_stats = {
         table = 'generic_stats',
         table = 'generic_stats',
         order = {},
         order = {},
Line 277: 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{
        name = 'Character',
        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)
 
    -- Parse stat args:
    tpl_args.stats = h.parse_stat_args(tpl_args)
   
    -- Loop through the stats then for each cargo row parse the map and
    -- store the cargo fields:
    local map = generic_stats_map
    for i,_ in pairs(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'] = 'generic_stats',
['header'] = tpl_args.name,
['subheader'] = nil,
[1] = string.format('[[File:%s_stats.png|250px]]', tpl_args.name),
[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 class
-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------
local character_map = {
tables.character_classes = {
     main = {
     table = 'character_classes',
        table = 'character_classes',
    order = {'flavour_text'},
        order = {'flavour_text'},
    parse_order = {'name', 'flavour_text', 'id', 'str_id', 'str', 'dex', 'int'},
        parse_order = {'name', 'flavour_text', 'id'},
    fields = {
        fields = {
        -- Header:
            -- Header:
        name = {
            name = {
            name = 'name',
                name = 'name',
            field = 'name',
                field = 'name',
            type = 'String',
                type = 'String',
            wikitext = i18n.character_class.name,
                wikitext = i18n.character_class.name,
        },
            },
        -- Main text:
            -- Main text:
        flavour_text = {
            flavour_text = {
            name = 'flavour_text',
                name = 'flavour_text',
            field = 'flavour_text',
                field = 'flavour_text',
            type = 'String',
                type = 'String',
            display = function(tpl_args, frame, value)
                display = function(tpl_args, frame, value)
                return m_util.html.poe_color('unique', value)
                    return m_util.html.poe_color('unique', value)
            end,
                end,
        },
            },
        -- Fields only:
            -- Fields only:
        id = {
            id = {
            name = nil,
                name = nil,
            field = 'id',
                field = 'id',
            type = 'Integer',
                type = 'Integer',
            wikitext = i18n.character_class.id,
                 wikitext = i18n.character_class.id,
            func = function(tpl_args, frame)
                 func = function(tpl_args, frame)
                 return m_game.constants.characters[tpl_args.name].id
                    return m_game.constants.characters[tpl_args.name].id
            end,
                 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,
         },
         },
     },
     },
}
}


local character_test_map = {
 
     main = {
tables.character_classes_test2 = {
        table = 'character_classes_test',
     table = 'character_classes_test2',
        order = {},
    order = {},
        parse_order = {'flavour_text_author'},
    parse_order = {'flavour_text_author'},
        fields = {
    fields = {
            flavour_text_author = {
        flavour_text_author = {
                name = nil,
            name = nil,
                field = 'flavour_text_author',
            field = 'flavour_text_author',
                type = 'String',
            type = 'String',
                func = function(tpl_args, frame, value)
            func = function(tpl_args, frame, value)
                    return 'John (JD) Doe'
                return 'Jane Smith'
                end,
            end,
            },
         },
         },
     },
     },
Line 426: 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}
p.declare_character_classes_test = m_util.cargo.declare_factory{data=character_test_map.main}
 
-- Attach cargo table:
p.attach_character_classes = m_util.cargo.attach_factory{data=character_map.main}
p.attach_character_classes_test = m_util.cargo.attach_factory{data=character_test_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 443: 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)


    -- Parse and store character test map:
    m_util.cargo.store(frame, h.parse_map(tpl_args, frame, character_test_map))
   
     -- 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 471: 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 492: 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 517: 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_class',
            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 584: 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 600: 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 625: 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 646: 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 674: 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 = '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,
},
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 = 'Integer',
            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)
                    local out = 1
 
                    if #results > 0 then  
                local out = 1
                        out = out + results[1][count]
                if #results > 0 then
                    end
                    out = out + results[1][count]
                   
                end
                    return out
 
                end,
                return out
            },
            end,
         },
         },
     },
     },
Line 884: 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)
function p.event_box(tpl_args, frame, map)
     -- 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 901: 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 922: 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 946: 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

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