mNo edit summary |
(Module:Cargo contains the most up-to-date cargo functions. Also DRY principle...) |
||
(19 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
local getArgs = require('Module:Arguments').getArgs |
local getArgs = require('Module:Arguments').getArgs |
||
− | local |
+ | local m_util = require('Module:Util') |
+ | local m_cargo = require('Module:Cargo') |
||
− | |||
+ | local f_item_link = require('Module:Item link').item_link |
||
− | local error = error |
||
− | local |
+ | local cargo = mw.ext.cargo |
− | local pairs = pairs |
||
local string_format = string.format |
local string_format = string.format |
||
Line 10: | Line 9: | ||
local mw_html = mw.html |
local mw_html = mw.html |
||
+ | |||
+ | local mw_language = mw.getLanguage('en') |
||
local p = {} |
local p = {} |
||
+ | local i18n = { |
||
− | ----- |
||
+ | categories = { |
||
− | |||
+ | versions = 'Versions', |
||
− | ------------------------------------------------------------------------------------------------------ |
||
+ | timelines = 'Timelines', |
||
− | -- Template: Version |
||
− | |||
− | local version_map = { |
||
− | version = { |
||
− | datatype = 'String', |
||
− | property = 'Is version', |
||
}, |
}, |
||
+ | |||
− | release_date = { |
||
− | + | show_date = { |
|
− | + | before = '← [[Version %s|%s]]<br>%s', |
|
+ | after = '[[Version %s|%s]] →<br>%s', |
||
}, |
}, |
||
− | + | version = { |
|
+ | required_args = 'Arguments "patch" and "patchdate" are required', |
||
− | datatype = 'Integer', |
||
− | + | multiple_versions = 'There are multiple versions with the same name', |
|
+ | header = '[[Version history|Version History]]', |
||
}, |
}, |
||
− | + | timeline = { |
|
− | + | version = 'Version', |
|
− | property = 'Has minor version part', |
||
− | }, |
||
− | patch_part = { |
||
− | datatype = 'Integer', |
||
− | property = 'Has patch version part', |
||
− | }, |
||
− | revision_part = { |
||
− | datatype = 'String', |
||
− | property = 'Has revision version part', |
||
− | }, |
||
− | before = { |
||
− | datatype = 'String', |
||
− | property = 'Has version before', |
||
− | show = function(this) |
||
− | local version = this.value |
||
− | local date = this.release_date |
||
− | if version and date then |
||
− | return string_format('← [[Version %s|%s]]<br>%s', version, version, date) |
||
− | else |
||
− | return '' |
||
− | end |
||
− | end, |
||
− | }, |
||
− | after = { |
||
− | datatype = 'String', |
||
− | property = 'Has version after', |
||
− | show = function(this) |
||
− | local version = this.value |
||
− | local date = this.release_date |
||
− | if version and date then |
||
− | return string_format('[[Version %s|%s]] →<br>%s', version, version, date) |
||
− | else |
||
− | return '' |
||
− | end |
||
− | end, |
||
}, |
}, |
||
} |
} |
||
+ | -- --------------------------------------------------------------------- |
||
− | local temp_map_for_cargo = {'version', 'release_date' } |
||
+ | -- Helper functions |
||
+ | -- --------------------------------------------------------------------- |
||
+ | h = {} |
||
+ | function h.cargo_query(tpl_args) |
||
− | p.version = function(frame) |
||
+ | --[[ |
||
− | local args = getArgs(frame, {parentFirst = true}) |
||
+ | Returns a Cargo query of all the results. |
||
− | local frame = util.misc.get_frame(frame) |
||
+ | |||
+ | 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. |
||
− | = p.version({ |
||
+ | |||
− | before = '2.4.1a', |
||
+ | Parameters |
||
− | patch = '2.4.1b', |
||
+ | ---------- |
||
− | patchdate = 'October 18, 2016', |
||
+ | value : String, required |
||
− | after = '2.4.2', |
||
− | + | 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 |
||
+ | -- --------------------------------------------------------------------- |
||
− | if not args.patch or not args.patchdate then |
||
+ | -- Template: Version |
||
− | error('Arguments "patch" and "patchdate" are required') |
||
+ | -- --------------------------------------------------------------------- |
||
+ | |||
+ | |||
+ | function validate_version(value) |
||
+ | if value == nil then |
||
+ | return value |
||
+ | else |
||
+ | return m_util.cast.version(value, {return_type='string'}) |
||
end |
end |
||
+ | end |
||
+ | function show_date(args) |
||
− | local version = util.cast.version(args.patch) |
||
+ | 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_struct = util.Struct(version_map) |
||
+ | local version_map = { |
||
− | version_struct:set('version', args.patch) |
||
+ | table = 'versions', |
||
− | version_struct:set('release_date', args.patchdate) |
||
+ | 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} |
||
− | local part_names = {'major_part', 'minor_part', 'patch_part', 'revision_part'} |
||
− | for i = 1, #part_names do |
||
− | local part = version[i] |
||
+ | p.version = function(frame) |
||
− | if part then |
||
+ | --[[ |
||
− | version_struct:set(part_names[i], part) |
||
+ | 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 |
||
+ | 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 |
end |
||
+ | -- Check and set 'before' and 'after' tpl_args |
||
− | |||
− | -- Check and set 'before' and 'after' args |
||
local edge_names = {'before', 'after'} |
local edge_names = {'before', 'after'} |
||
− | for |
+ | for _, key in ipairs(edge_names) do |
− | local v = |
+ | local v = tpl_args[key] |
if v then |
if v then |
||
− | local |
+ | local results = cargo.query( |
+ | 'versions', |
||
− | |||
− | + | 'versions.release_date', |
|
+ | { |
||
− | string_format('[[Is version::%s]] [[Has release date::+]]', edge_version), |
||
− | + | where=string.format('version="%s"', v), |
|
− | + | -- Cargo bug work around |
|
− | + | groupBy='versions._pageID', |
|
+ | } |
||
+ | ) |
||
if #results == 1 then |
if #results == 1 then |
||
+ | tpl_args[string.format('%s_date', key)] = results[1]['versions.release_date'] |
||
− | version_struct:set(edge_names[i], edge_version) |
||
− | version_struct:set_prop(edge_names[i], 'release_date', results[1]['Has release date']) |
||
elseif #results > 1 then |
elseif #results > 1 then |
||
− | error( |
+ | error(i18n.version.multiple_versions) |
end |
end |
||
end |
end |
||
end |
end |
||
+ | |||
− | |||
− | -- Set |
+ | -- Set Cargo data |
− | local |
+ | local _properties = { |
+ | _table = version_map.table, |
||
− | local props_cargo = { |
||
− | _table = 'Versions', |
||
} |
} |
||
− | for |
+ | for key, data in pairs(version_map.fields) do |
− | + | if tpl_args[key] ~= nil then |
|
+ | _properties[data.field] = tpl_args[key] |
||
− | if value then |
||
+ | end |
||
− | props_smw[version_struct:get_prop(i, 'property')] = value |
||
− | end |
||
− | --props_cargo[i] = value or '' |
||
end |
end |
||
+ | |||
− | |||
− | + | m_cargo.store(frame, _properties) |
|
− | |||
− | |||
− | for i = 1, #temp_map_for_cargo do |
||
− | local v = temp_map_for_cargo[i] |
||
− | props_cargo[v] = version_struct:get(v) or '' |
||
− | end |
||
− | |||
− | -- mw.logObject(props_cargo) |
||
− | util.cargo.store(frame, props_cargo) |
||
− | |||
-- Generate output |
-- Generate output |
||
+ | local release_date = h.date(tpl_args.patchdate) |
||
− | -- todo: rework it somehow |
||
− | local release_date = frame:callParserFunction('#show: Version ' .. version_struct:get('version'), {'?Has release date'}) |
||
− | |||
local tbl = mw_html.create('table') |
local tbl = mw_html.create('table') |
||
tbl |
tbl |
||
Line 166: | Line 274: | ||
:tag('th') |
:tag('th') |
||
:attr('colspan', 3) |
:attr('colspan', 3) |
||
− | :wikitext( |
+ | :wikitext(i18n.version.header) |
:done() |
:done() |
||
:done() |
:done() |
||
Line 172: | Line 280: | ||
:tag('td') |
:tag('td') |
||
:cssText('width: 30%') |
:cssText('width: 30%') |
||
− | :wikitext( |
+ | :wikitext(version_map.fields.before.show(tpl_args, frame)) |
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
:cssText('width: 40%') |
:cssText('width: 40%') |
||
− | :wikitext(string_format(' |
+ | :wikitext(string_format('<b>%s</b><br>%s', tpl_args.patch, release_date)) |
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
:cssText('width: 30%') |
:cssText('width: 30%') |
||
− | :wikitext( |
+ | :wikitext(version_map.fields.after.show(tpl_args, frame)) |
local cats = { |
local cats = { |
||
− | + | i18n.categories.versions, |
|
} |
} |
||
− | return tostring(tbl) .. |
+ | return tostring(tbl) .. m_util.misc.add_category(cats) |
end |
end |
||
Line 193: | Line 301: | ||
p.version_declare = function(frame) |
p.version_declare = function(frame) |
||
-- local args = getArgs(frame, {parentFirst = true}) |
-- local args = getArgs(frame, {parentFirst = true}) |
||
− | local frame = |
+ | local frame = m_util.misc.get_frame(frame) |
local props = { |
local props = { |
||
Line 211: | Line 319: | ||
--mw.logObject(props) |
--mw.logObject(props) |
||
− | return |
+ | return m_cargo.declare(frame, props) |
end |
end |
||
− | ----- |
||
− | -- |
+ | -- --------------------------------------------------------------------- |
+ | -- Timeline |
||
− | -- Template: Version history list |
||
+ | -- --------------------------------------------------------------------- |
||
− | p.version_history_list = function(frame) |
||
− | local args = getArgs(frame, {parentFirst = true}) |
||
− | local frame = util.misc.get_frame(frame) |
||
+ | function p.timeline(frame) |
||
− | -- = p.version_history_list({conditions='[[Is version::~1*||~2*]]'}) |
||
+ | --[[ |
||
− | -- = p.version_history_list({conditions='[[Is version::~0.9*]]'}) |
||
+ | Add a timeline when versions or items were added to the game. |
||
− | -- = p.version_history_list({conditions='[[Is version::~0.5*]]'}) |
||
+ | |||
− | |||
+ | Examples: |
||
− | if args.conditions then |
||
+ | = p.timeline{ |
||
− | args.conditions = args.conditions .. '[[Has release date::+]]' |
||
+ | tables = 'versions', |
||
− | else |
||
− | + | fields = 'versions.version, versions.release_date', |
|
+ | q_where = 'versions.version <> ""', |
||
− | end |
||
+ | q_orderBy = 'versions.version DESC, versions.release_date ASC' |
||
− | |||
− | local query = { |
||
− | args.conditions, |
||
− | '?Is version', |
||
− | '?Has release date', |
||
− | sort = 'Has release date, Is version', |
||
− | order = 'desc, desc', |
||
− | link = 'none', |
||
− | offset = 0, |
||
} |
} |
||
+ | |||
+ | = 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) |
||
− | repeat |
||
+ | |||
− | local result = util.smw.query(query, frame) |
||
+ | -- Preallocate: |
||
− | 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 out = {} |
||
− | local |
+ | local last_main_version |
+ | local last_minor_version |
||
− | |||
+ | local current_version |
||
− | for i = 1, #results do |
||
− | + | local result_list |
|
+ | |||
− | local date = result['Has release date'] |
||
+ | -- Loop through all the results from the query: |
||
− | local version = result['Is version'] |
||
+ | for i, result in ipairs(results) do |
||
− | |||
− | + | release_version = result['versions.version'] |
|
+ | |||
− | local minor_version = table_concat({v[1], v[2], v[3]}, '.') -- todo: rework it |
||
+ | local v = m_util.cast.version(release_version) |
||
− | |||
− | + | local version_h2 = table.concat({v[1], v[2]}, '.') |
|
− | + | ||
+ | if release_version ~= last_minor_version then |
||
− | out[#out + 1] = tostring(current_list) |
||
+ | |||
+ | 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 |
end |
||
+ | |||
− | |||
+ | current_version |
||
− | out[#out + 1] = string_format('===Version %s===', minor_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 |
end |
||
+ | |||
− | |||
+ | -- Save the last list: |
||
− | current_list:tag('li'):wikitext(string_format('%s – [[Version %s]]', date, version)) |
||
+ | if (i == #results) and (current_version ~= nil) then |
||
− | |||
+ | out[#out + 1] = tostring(current_version) |
||
− | -- save the last list |
||
− | if i == #results and current_list ~= nil then |
||
− | out[#out + 1] = tostring(current_list) |
||
end |
end |
||
+ | |||
− | |||
− | + | last_main_version = version_h2 |
|
+ | last_minor_version = release_version |
||
end |
end |
||
+ | |||
− | |||
+ | -- Add categories: |
||
− | return table_concat(out, '\n') |
||
+ | local cats = { |
||
− | end |
||
+ | i18n.categories.timelines, |
||
− | |||
− | ----- |
||
− | |||
− | p.version_history_list_2 = function(frame) |
||
− | local args = getArgs(frame, {parentFirst = true}) |
||
− | local frame = 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, |
||
} |
} |
||
+ | |||
− | |||
+ | return table.concat(out, '\n') .. m_util.misc.add_category(cats) |
||
− | local results = {} |
||
− | repeat |
||
− | local result = 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 – [[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 |
end |
||
Latest revision as of 01:34, 2 May 2021
The above documentation is transcluded from Module:Version/doc.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
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 = '← [[Version %s|%s]]<br>%s',
after = '[[Version %s|%s]] →<br>%s',
},
version = {
required_args = 'Arguments "patch" and "patchdate" are required',
multiple_versions = 'There are multiple versions with the same name',
header = '[[Version history|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('<b>%s</b><br>%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