Module:Sandbox/Illviljan/Data tables

From Path of Exile Wiki
Jump to navigation Jump to search
Module documentation[create] [purge]
--[[
    Module for data tables
    
]]

local getArgs = require('Module:Arguments').getArgs
local util = require('Module:Util')
local game = require('Module:Game')
local f_infocard = require('Module:Infocard')._main
local mw_language = mw.getLanguage('en')

local p = {}

local i18n = {
    character_class = {
    
    },
    ascendancy_class = {
    
    },
    event = {
        
    },
}

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

function h.date(value, args)
    --[[
    Format dates in correct and useable form.
    
    value = date string
    args = table of extra 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',
        },
    }
    
    local date_format = arg_list.format.default
    for i,v in pairs(args) do
        if i == 'format' then
            date_format = arg_list[i][v]            
        end
    end
    local out
    if value ~= nil then
        out = mw_language:formatDate(date_format, value)
    else
        out =  nil
    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.
    ]]
    
	if str ~= nil and str:sub(-1,-1) == 'Z' then  
		return 'UTC'
	else
		return ''
	end
end

function h.cargo_query(tpl_args)
    --[[
    Returns a Cargo query of all the results, even if there are more
    results than the maximum query limit. It also adds popular fields. 
    
    tpl_args should include these keys:
    tpl_args.tables
    tpl_args.fields
    tpl_args.q_*
    
    ]]
    
    local tables = util.string.split(tpl_args.tables, ', ')
    local fields = util.string.split(tpl_args.fields, ', ')
    
    -- Parse query arguments
    local query = {
        -- Workaround: Fix duplicates but removes other rows as well. 
        groupBy = tables[1] .. '._pageID',
        limit = 5000,
        offset = 0,
    }
    for key, value in pairs(tpl_args) do 
        if string.sub(key, 0, 2) == 'q_' then
            query[string.sub(key, 3)] = value
        end
    end
    
    -- Add commonly used fields:
    fields_base = {
        '_pageNamespace', 
        '_pageTitle',
        '_ID',
        '_rowID',
        '_pageID',
        '_pageName'
        -- '_value'
    }
    for _, tbl in ipairs(tables) do
        for _, fld in ipairs(fields_base) do
            fields[#fields+1] = string.format('%s.%s', tbl, fld)
        end
    end
    
    -- Query cargo table. If there are too many results then repeat, 
    -- offset, re-query and add the remaining results:
    local results = {}      
    repeat
        local result = mw.ext.cargo.query(
            table.concat(tables, ', '),
            table.concat(fields, ', '),
            query
        )
        query.offset = query.offset + #result

        for _,v in ipairs(result) do
            results[#results + 1] = v
        end
    until #result < query.limit
    
    return results
end

function h.parse_map(tpl_args, frame, map)
    --[[
        Parse the map
        
        Input:
        
    ]]
    local cargo_data = {
        _table = map.main.table,
    }
    for _, key in pairs(map.main.parse_order) do
        local data = map.main.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

-- ---------------------------------------------------------------------
-- Template: Character classes
-- ---------------------------------------------------------------------
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 = 'Name',
            },
            -- Main text:
            flavour_text = {
                name = 'flavour_text',
                field = 'flavour_text',
                type = 'String',
                display = function(tpl_args, frame, value)
                    return util.html.poe_color('unique', value)
                end,
            },
            -- Fields only:
            id = {
                name = nil,
                field = 'id',
                type = 'String',
                wikitext = 'Id',
                func = function(tpl_args, frame)
                    return game.constants.characters[tpl_args.name].id
                end,
            },
        },
    },
}

local character_test_map = {
    main = {
        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,
            },
        },
    },
}

-- Declare cargo table:
p.declare_character_classes = util.cargo.declare_factory{data=character_map.main}
p.declare_character_classes_test = util.cargo.declare_factory{data=character_test_map.main}

-- Attach cargo table:
p.attach_character_classes = util.cargo.attach_factory{data=character_map.main}
p.attach_character_classes_test = util.cargo.attach_factory{data=character_test_map.main}


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 args
    local tpl_args = getArgs(frame, {parentFirst = true})
    local frame = util.misc.get_frame(frame)
	    
    -- Parse character map:
    local map = character_map
    local parsed_map = h.parse_map(tpl_args, frame, map)
    tpl_args = parsed_map.tpl_args
    local cargo_data = parsed_map.cargo_data
    
    -- Parse and store character test map:
    -- util.cargo.store(frame, h.parse_map(tpl_args, frame, character_test_map))
    
    -- Store cargo fields:
    util.cargo.store(frame, cargo_data)  
 
    -- 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_class',
		['header'] = tpl_args.name,
		['subheader'] = nil,
		[1] = string.format(
            '[[File:%s character class.png|250px]]',
            tpl_args.name
        ),
		[2] = tostring(tbl),
    }
    
    -- cats
    local cats = {
        'Character Classes'
    }
    
    return f_infocard(infocard_args) .. util.misc.add_category(cats)
end



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

return p