Module:Achievement
Usage
Called by {{#if:{{#switch: yes
| y | yes | t | true | on | 1 = yes | n | no | f | false | off | 0 | = | = | #default = yes
}}|}}{{{{#if: |subst: }}[[{{#if: {{#pos: AchievementRow | : }} || Template: }}AchievementRow|{{ #ifeq: | Template | AchievementRow | AchievementRow }}]]{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}}}{{#if:{{#switch: yes
| y | yes | t | true | on | 1 = yes
| n | no | f | false | off | 0 | =
| =
| #default = yes
}}|
}}{{#if: {{#pos: AchievementRow | File: }}{{#pos: AchievementRow | Category: }} | }} and {{#if:{{#switch: yes
| y | yes | t | true | on | 1 = yes | n | no | f | false | off | 0 | = | = | #default = yes
}}|}}{{{{#if: |subst: }}[[{{#if: {{#pos: Load achievements | : }} || Template: }}Load achievements|{{ #ifeq: | Template | Load achievements | Load achievements }}]]{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}}}{{#if:{{#switch: yes
| y | yes | t | true | on | 1 = yes
| n | no | f | false | off | 0 | =
| =
| #default = yes
}}|
}}{{#if: {{#pos: Load achievements | File: }}{{#pos: Load achievements | Category: }} | }}
{{#if:{{#pos:Achievement|/sandbox}}|| ko:모듈:Achievement pt:Módulo:Achievement }}
local achievement_page = 'Achievement'
local p = {}
local namespace = mw.title.getCurrentTitle().nsText
local page_title = mw.title.getCurrentTitle().text
local full_title = mw.title.getCurrentTitle().fullText
local html
local frame
local function sanitize(str)
-- remove anything between < and > (simple way to remove span tag)
-- return lower case alpha numeric characters and spaces
return str:gsub('<.->',''):gsub('[^%w%s%?]*', ''):lower()
end
local function trim(str)
local trimmed = (str and mw.text.trim(str) ~= "" and mw.text.trim(str))
return trimmed
end
-- Adds one row of achievement data to html object
local function printLine(line, is_input)
local tr = html:tag('tr'):attr('id', line.title):cssText('text-align:left')
local link = nil
if not is_input then
link = achievement_page..'#'..line.title
end
local achievementIcon = require('Module:SpriteFile').sprite({name='AchievementSprite', sanitize(line.title), size=94, align='middle', scale=0.5, link=link})
local newAchievementIcon = require('Module:SpriteFile').sprite({name='NewAchievementSprite', sanitize(line.title), height = 48, width = 84, align='middle', link=link})
tr:tag('td'):wikitext(achievementIcon):cssText('text-align:center')
tr:tag('td'):wikitext(newAchievementIcon):cssText('text-align:center')
local title_extra = ''
if line.upcoming_ver then
title_extra = title_extra .. frame:expandTemplate{title = 'Upcoming', args = {ver = line.upcoming_ver}}
end
if line.until_ver then
title_extra = title_extra .. frame:expandTemplate{title = 'Until', args = {ver = line.until_ver}}
end
tr:tag('td'):wikitext('[['..(link or full_title)..'|'..line.title..']]', title_extra)
tr:tag('td'):wikitext(line.game_description)
tr:tag('td'):wikitext(line.wiki_description)
tr:tag('td'):wikitext(line.gamerscore)
tr:tag('td'):wikitext(line.trophy_type)
if is_input then -- These are only displayed on the input page, not on individual content pages
tr:tag('td'):wikitext(line.reward)
end
end
-- Puts one line of data into SMW for later querying
local function storeLine(line)
-- Put data into SMW
-- The only top level params that are needed is stuff that would be used as selectors
-- everything else is put into a json blob for flexibility
if not (namespace == '' or namespace == 'Minecraft_Wiki') then
return -- only store data if we are in main or Minecraft_Wiki namespaces
end
local smw_sub = {}
local sanitized_title = sanitize(line.title)
local subname = 'ACHIEVEMENT'..'_'..sanitized_title
-- mw.text.unstrip gets rid of parser artifacts that are put there when a <ref> tag is used.
line.wiki_description = mw.text.unstrip(line.wiki_description)
line.game_description = mw.text.unstrip(line.game_description)
local smw_sub = { -- the actual SMW sub-object
['Achievement Title'] = sanitized_title,
['Achievement JSON'] = mw.text.jsonEncode(line) -- serializes all data into a json blob
}
mw.smw.subobject(smw_sub, subname)
end
-- Public function - Called by {{AchievementRow}}
function p.inputLine(_frame)
frame = _frame -- store frame for later use by expandTemplate
local args = frame:getParent().args
-- Normalize inputs and set defaults
local line = {
title = args['title'], -- name
upcoming_ver = args['upcoming'], -- version where achievement will be introduced
until_ver = args['until'], -- version where achievement will be removed
game_description = trim(args[1]) or "—",
wiki_description = trim(args[2]) or "—",
gamerscore = trim(args[3]) or '—',
trophy_type = trim(args[4]) or '—',
reward = trim(args[5]) or '—',
}
html = mw.html.create()
printLine(line, true)
storeLine(line)
return html
end
local function printHeader(short_header)
-- Can't use table tag because it will close itself, but we need to close it with footer
html = mw.html.create():wikitext('<div style="overflow: auto;"><table class="wikitable collapsible sortable" style="text-align:center">')
local th = html:tag('tr'):tag('th'):addClass('unsortable'):attr('colspan', 8)
local tr = html:tag('tr')
tr:tag('th'):wikitext('Icon'):attr('colspan', 2):addClass('unsortable')
tr:tag('th'):wikitext('Achievement'):attr('rowspan', 2):addClass('sortable')
tr:tag('th'):wikitext('In-game description'):attr('rowspan', 2):addClass('unsortable')
tr:tag('th'):wikitext('Actual requirements (if different)'):attr('rowspan', 2):addClass('unsortable')
tr:tag('th'):wikitext('Gamerscore earned'):attr('rowspan', 2):addClass('sortable')
tr:tag('th'):wikitext('Trophy type (<span class="explain" title="PlayStation">PS</span>)'):attr('rowspan', 2):addClass('sortable')
if not short_header then
tr:tag('th'):wikitext('Rewards'):attr('rowspan', 2)
end
html:tag('th'):wikitext('PS4'):addClass('unsortable')
html:tag('th'):wikitext('Other'):addClass('unsortable')
return html
end
local function printFooter()
return '</table></div>'
end
-- Public function - called by {{AchievementTable}}
function p.table(frame)
local args = frame:getParent().args
if args[1] == 'foot' then
return printFooter()
else
return printHeader(false)
end
end
-- Public function - called by {{Load achievements}}
function p.load(frame_)
frame = frame_ -- store frame for later use by expandTemplate
local args = frame:getParent().args
achievement_page = args.page or achievement_page
printHeader(true)
local queryString = {}
-- SMW can query up to 15 conditions at once and we always specify the source page, so put queries into groups of 13 names
local counter = 13 -- Start at 13 so queryString index starts at 1, it just looks cleaner when debugging
for name in string.gmatch(args[1], "[^;]+") do
counter = counter + 1
queryString[math.floor(counter/13)] = (queryString[math.floor(counter/13)] or '')..'||'..sanitize(name)
end
local expected = counter - 13
local found = 0
for _,str in ipairs(queryString) do
local query = {
'[[-Has subobject::'..achievement_page..']]',
'[[Achievement Title::'..str:sub(3)..']]', --Remove the first 2 characters because they will always be ||
'?Achievement JSON',
limit = 25
}
local smwdata = mw.smw.ask(query)
if smwdata then
for i,v in ipairs(smwdata) do
if type(v['Achievement JSON']) == "table" then -- if a page has a drop happening multiple times it is returned in a table instead of a string
for j,k in ipairs(v['Achievement JSON']) do
found = found + 1
local line = mw.text.jsonDecode(v['Achievement JSON'][j] or '{}')
printLine(line, false)
end
else
found = found + 1
local line = mw.text.jsonDecode(v['Achievement JSON'] or '{}')
printLine(line, false)
end
end
end
end
if found ~= expected then
html:wikitext('[[Category:Missing achievement]]')
end
html:wikitext(printFooter())
return html
end
return p