Module:Version

local getArgs = require('Module:Arguments').getArgs local m_util = require('Module:Util') local m_cargo = require('Module:Cargo') 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 i18n = { categories = { versions = 'Versions', timelines = 'Timelines', },   show_date = { before = '← %s %s', after = '%s → %s', },   version = { required_args = 'Arguments "patch" and "patchdate" are required', multiple_versions = 'There are multiple versions with the same name', header = 'Version History', },   timeline = { version = 'Version', }, }

-- - -- Helper functions -- -

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

function h.date(value, args) --   Format dates in correct and useable form.    Parameters    --    value : String, required        Date    args : Table        Table with extra formatting args. local args = args or {} -- List of allowed extra arguments: local arg_list = { format = { default = 'F j, Y H:i:s', cargo  = 'Y-m-d H:i:s', no_time = 'F j, Y', },   }    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

-- - -- 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 = h.date(date) or '' if args.key == 'before' then return string_format(i18n.show_date.before, version, version, date) elseif args.key == 'after' then return string_format(i18n.show_date.after, 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 = 'previous', 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_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.1',        patch = '2.4.1b',        patchdate = 'October 18, 2016',        after = '2.4.2',    }    --

local tpl_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 tpl_args[k] = data.validate(tpl_args[k]) end end -- Workaround for patchdate returning the string 'nil' when it's nil, -- not sure if that's intentional: if not tpl_args.patch or not tpl_args.patchdate or tpl_args.patchdate == 'nil' then error(i18n.version.required_args) end local version_parts = m_util.cast.version(tpl_args.patch, {return_type='table'}) tpl_args.major_part = tonumber(version_parts[1]) tpl_args.minor_part = tonumber(version_parts[2]) tpl_args.patch_part = tonumber(version_parts[3]) if version_parts[4] then tpl_args.revision_part = version_parts[4] end

-- Check and set 'before' and 'after' tpl_args local edge_names = {'before', 'after'} for _, key in ipairs(edge_names) do       local v = tpl_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 tpl_args[string.format('%s_date', key)] = results[1]['versions.release_date'] elseif #results > 1 then error(i18n.version.multiple_versions) end end end

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

-- Generate output local release_date = h.date(tpl_args.patchdate) local tbl = mw_html.create('table') tbl :addClass('wikitable successionbox') :tag('tr') :tag('th') :attr('colspan', 3) :wikitext(i18n.version.header) :done :done :tag('tr') :tag('td') :cssText('width: 30%') :wikitext(version_map.fields.before.show(tpl_args, frame)) :done :tag('td') :cssText('width: 40%') :wikitext(string_format('%s %s', tpl_args.patch, release_date)) :done :tag('td') :cssText('width: 30%') :wikitext(version_map.fields.after.show(tpl_args, frame))

local cats = { i18n.categories.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_cargo.declare(frame, props) end

-- - -- Timeline -- -

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', h.date(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 = { i18n.categories.timelines, }   return table.concat(out, '\n') .. m_util.misc.add_category(cats) end

-

return p