A large portion of relevant modules/templates have now been switched to cargo. Various usages of SMW throughout the wiki need to be replaced by the new functions, in particular item tables. If some pages do not show up but contain no errors, please null-edit them. To see how you can help with the port check out Path_of_Exile_Wiki:To-do_list/SMW_migration (and leave a comment on the talk page if you have questions).

Module:Version

From Path of Exile Wiki
Jump to: navigation, search
local getArgs = require('Module:Arguments').getArgs
local m_util = require('Module:Util')
local f_item_link = require('Module:Item link').item_link
local cargo = mw.ext.cargo

local string_format = string.format
local table_concat = table.concat

local mw_html = mw.html

local mw_language = mw.getLanguage('en')

local p = {}

local date_format = 'd F Y H:i:s'

local i18n = {
    timeline = {
        version = 'Version',
    },
}

-- ---------------------------------------------------------------------
-- Helper
-- ---------------------------------------------------------------------

h = {}

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_util.cargo.query(tables, fields, query, args)
    
    return results
end


-- ---------------------------------------------------------------------
-- Template: Version
-- ---------------------------------------------------------------------


function validate_version(value)
    if value == nil then
        return value
    else
        return m_util.cast.version(value, {return_type='string'})
    end
end

function show_date(args)
    return function(tpl_args, frame)
        local version = tpl_args[args.key]
        local date = tpl_args[string.format('%s_date', args.key)]
        if version and date then
            date = mw_language:formatDate(date_format, date)
            if args.key == 'before' then
                return string_format('← [[Version %s|%s]]<br>%s', version, version, date)
            elseif args.key == 'after' then
                return string_format('[[Version %s|%s]] →<br>%s', version, version, date)
            end
        else
            return ''
        end
    end
end


local version_map = {
    table = 'versions',
    fields = {
        patch = {
            field = 'version',
            type = 'String',
            validate = validate_version,
        },
        patchdate = {
            field = 'release_date',
            type = 'Datetime',
            validate = tostring,
        },
        major_part = {
            field = 'major_part',
            type = 'Integer',
        },
        minor_part = {
            field = 'minor_part',
            type = 'Integer',
        },
        patch_part = {
            field = 'patch_part',
            type = 'Integer',
        },
        revision_part = {
            field = 'revision_part',
            type = 'String',
        },
        before = {
            field = 'before',
            type = 'String',
            validate = validate_version,
            show = show_date{key='before'},
        },
        after = {
            field = 'after',
            type = 'String',
            validate = validate_version,
            show = show_date{key='after'},
        },
    },
}

p.table_versions = m_util.cargo.declare_factory{data=version_map}

p.version = function(frame)
    --[[
    This function creates a infobox and stores the data in a cargo table.
    
    Examples:
    = p.version({
        before = '2.4.1a',
        patch = '2.4.1b',
        patchdate = 'October 18, 2016',
        after = '2.4.2',
    })
    --]]

    local args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)

    for k, data in pairs(version_map.fields) do
        if data.validate ~= nil then
            args[k] = data.validate(args[k])
        end
    end

    if not args.patch or not args.patchdate then
        error('Arguments "patch" and "patchdate" are required')
    end
    
    local version_parts = m_util.cast.version(args.patch, {return_type='table'})
    args.major_part = tonumber(version_parts[1])
    args.minor_part = tonumber(version_parts[2])
    args.patch_part = tonumber(version_parts[3])
    if version_parts[4] then
        args.revision_part = version_parts[4]
    end

    -- Check and set 'before' and 'after' args
    local edge_names = {'before', 'after'}
    for _, key in ipairs(edge_names) do
        local v = args[key]
        if v then
            local results = cargo.query(
                'versions', 
                'versions.release_date', 
                {
                    where=string.format('version="%s"', v),
                    -- Cargo bug work around
                    groupBy='versions._pageID',
                }
            )
            if #results == 1 then
                args[string.format('%s_date', key)] = results[1]['versions.release_date']
            elseif #results > 1 then
                error('There are multiple versions with the same name')
            end
        end
    end


    -- Set Cargo data
    local _properties = {
        _table = version_map.table,
    }
    for key, data in pairs(version_map.fields) do
        if args[key] ~= nil then
            _properties[data.field] = args[key]
       end
    end
    
    m_util.cargo.store(frame, _properties)


    -- Generate output
    -- todo: rework it somehow
    local release_date = mw_language:formatDate(date_format, args.patchdate)

    local tbl = mw_html.create('table')
    tbl
        :addClass('wikitable successionbox')
        :tag('tr')
            :tag('th')
                :attr('colspan', 3)
                :wikitext('[[Version history|Version History]]')
                :done()
            :done()
        :tag('tr')
            :tag('td')
                :cssText('width: 30%')
                :wikitext(version_map.fields.before.show(args, frame))
                :done()
            :tag('td')
                :cssText('width: 40%')
                :wikitext(string_format('<b>%s</b><br>%s', args.patch, release_date))
                :done()
            :tag('td')
                :cssText('width: 30%')
                :wikitext(version_map.fields.after.show(args, frame))

    local cats = {
        'Versions',
    }

    return tostring(tbl) .. m_util.misc.add_category(cats)
end

-----

p.version_declare = function(frame)
    -- local args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)

    local props = {
        _table = 'Versions',
    }

--    for i, _ in pairs(version_map) do
--        props[i] = _.datatype
--    end

    for i = 1, #temp_map_for_cargo do
        local v = temp_map_for_cargo[i]
        local _ = version_map[v]
        props[v] = _.datatype
    end

    --mw.logObject(props)

    return m_util.cargo.declare(frame, props)
end

-----

------------------------------------------------------------------------------------------------------
-- Template: Version history list

p.version_history_list = function(frame)
    local args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)

    -- = p.version_history_list({conditions='[[Is version::~1*||~2*]]'})
    -- = p.version_history_list({conditions='[[Is version::~0.9*]]'})
    -- = p.version_history_list({conditions='[[Is version::~0.5*]]'})

    if args.conditions then
        args.conditions = args.conditions .. '[[Has release date::+]]'
    else
        args.conditions = '[[Is version::+]][[Has release date::+]]'
    end

    local query = {
        args.conditions,
        '?Is version',
        '?Has release date',
        sort = 'Has release date, Is version',
        order = 'desc, desc',
        link = 'none',
        offset = 0,
    }

    local results = {}
    repeat
        local result = m_util.smw.query(query, frame)
        local length = #result
        query.offset = query.offset + length

        for i = 1, length do
            results[#results + 1] = result[i]
        end
    until length < 1000

    local out = {}
    local last_minor_version, current_list

    for i = 1, #results do
        local result = results[i]
        local date = result['Has release date']
        local version = result['Is version']

        local v = m_util.cast.version(result['Is version'])
        local minor_version = table_concat({v[1], v[2], v[3]}, '.') -- todo: rework it

        if minor_version ~= last_minor_version then
            if current_list ~= nil then
                out[#out + 1] = tostring(current_list)
            end

            out[#out + 1] = string_format('===Version %s===', minor_version)
            current_list = mw_html.create('ul')
        end

        current_list:tag('li'):wikitext(string_format('%s &ndash; [[Version %s]]', date, version))

        -- save the last list
        if i == #results and current_list ~= nil then
            out[#out + 1] = tostring(current_list)
        end

        last_minor_version = minor_version
    end

    return table_concat(out, '\n')
end

-----

p.version_history_list_2 = function(frame)
    local args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)

    -- = p.version_history_list({conditions='[[Is version::~1*||~2*]]'})
    -- = p.version_history_list({conditions='[[Is version::~0.9*]]'})
    -- = p.version_history_list({conditions='[[Is version::~0.5*]]'})

    if args.conditions then
        args.conditions = args.conditions .. '[[Has release date::+]]'
    else
        args.conditions = '[[Is version::+]] [[Has release date::+]]'
    end

    local query = {
        args.conditions,
        '?Is version',
        '?Has release date',
        '?Has major version part',
        '?Has minor version part',
        '?Has patch version part',
--        '?Has revision version part',
        sort = 'Has major version part, Has minor version part, Has patch version part, Is version',
        order = 'desc, desc, desc, desc',
        link = 'none',
        offset = 0,
    }

    local results = {}
    repeat
        local result = m_util.smw.query(query, frame)
        local length = #result
        query.offset = query.offset + length

        for i = 1, length do
            results[#results + 1] = result[i]
        end
    until length < 1000

--    mw.logObject(results)

    local out = {}
    local last_minor_version, current_list

    for i = 1, #results do
        local result = results[i]
        local date = result['Has release date']
        local version = result['Is version']

        local patch_version = string_format('%s.%s.%s',
            result['Has major version part'], result['Has minor version part'], result['Has patch version part'])

        if patch_version ~= last_minor_version then
            if current_list ~= nil then
                out[#out + 1] = tostring(current_list)
            end

            out[#out + 1] = string_format('===Version %s===', patch_version)
            current_list = mw_html.create('ul')
        end

        current_list:tag('li'):wikitext(string_format('%s &ndash; [[Version %s]]', date, version))

        -- save the last list
        if i == #results and current_list ~= nil then
            out[#out + 1] = tostring(current_list)
        end

        last_minor_version = patch_version
    end

    return table_concat(out, '\n')
end

function p.timeline(frame) 
    --[[ 
    Add a timeline when versions or items were added to the game.
    
    Examples:
    = p.timeline{
        tables = 'versions',
        fields = 'versions.version, versions.release_date',
        q_where = 'versions.version <> ""',
        q_orderBy = 'versions.version DESC, versions.release_date ASC'
    }
    
    = p.timeline{
        tables = 'versions, items',        
        fields = 'versions.version, versions.release_date, versions._pageName, items.class, items._pageName, items.name, items.release_version, items.inventory_icon, items.html',
        q_join = 'versions.version=items.release_version',
        q_where = 'versions.version IS NOT NULL AND items.release_version IS NOT NULL AND items.rarity = "Unique"',
        q_orderBy = 'versions.version DESC, versions.release_date ASC, items.name ASC',
        q_groupBy = 'versions._pageID, items.name',
        q_limit = 5000,
    }
    
    ]]
    
    -- Get args:
    local tpl_args = getArgs(frame, {parentFirst = true})
    local frame = m_util.misc.get_frame(frame)

    -- Query results:
    local results = h.cargo_query(tpl_args)
    
    -- Preallocate:
	local out = {}
	local last_main_version 
    local last_minor_version
    local current_version
    local result_list
    
    -- Loop through all the results from the query:
	for i, result in ipairs(results) do 
		release_version = result['versions.version']
		
		local v = m_util.cast.version(release_version)
		local version_h2 = table.concat({v[1], v[2]}, '.')
        
		if release_version ~= last_minor_version then
            
			if version_h2 ~= last_main_version then 
				if current_version ~= nil then
					out[#out + 1] = tostring(current_version)
				end
				
				out[#out+1] = string.format(
                    '===%s %s===', 
                    i18n.timeline.version, 
                    table.concat({v[1], v[2], 0}, '.')
                ) 
				current_version = mw.html.create('ul')
			end
		
			current_version
				:tag('li')
					:wikitext(string.format(
                        '%s - [[%s %s]]', 
                        result['versions.release_date'], 
                        i18n.timeline.version, 
                        release_version, 
                        result['versions.version'])
                    )
			result_list = current_version:tag('ol')
		end 
		
              
        -- If the result has an item class, then add another list with 
        -- the results.
        if result['items.class'] ~= nil then 
            -- result_list:tag('li'):wikitext(string.format('%s', 
                -- f_item_link{
                    -- page=result['items._pageName'], 
                    -- name=result['items.name'],
                    -- inventory_icon=result['items.inventory_icon'] or '', 
                    -- html=result['items.html'] or '', 
                    -- skip_query=true
                    -- }
                -- )
            -- )
            result_list:tag('li'):wikitext(string.format('[[%s]]', 
                result['items._pageName']
                )
            )
        end
        
        -- Save the last list:
		if (i == #results) and (current_version ~= nil) then 
			out[#out + 1] = tostring(current_version)
		end
		
		last_main_version = version_h2
		last_minor_version = release_version
	end
	
	-- Add categories:
    local cats = {
		'Timelines',
    }
	
	return table.concat(out, '\n') .. m_util.misc.add_category(cats)
end

-----

return p