Module:Universe: Difference between revisions
From PC Gaming Shelter
No edit summary |
No edit summary |
||
| Line 423: | Line 423: | ||
local query = { | local query = { | ||
'[[Member of::' .. clan .. ']]', | '[[-Member of::' .. clan .. ']]', | ||
} | } | ||
Revision as of 17:34, 5 August 2026
Documentation for this module may be created at Module:Universe/doc
local utils = require( 'Module:Utils' )
local p = {}
local function getCurrentGame()
local title = mw.title.getCurrentTitle()
local game = title.rootText
local resource = title.subpageText
local data = {
['game'] = game,
['resource'] = resource,
}
return data
end
local function setDisplayTitle(frame, title)
local displayTitle = frame:preprocess(string.format('{{DISPLAYTITLE:%s|noreplace, noerror}}', title))
return displayTitle
end
local function escapePattern(value)
return value:gsub('([^%w])', '%%%1')
end
local function removeGameFromLabels(results, game)
local gamePattern = escapePattern(game)
for index, link in ipairs(results) do
results[index] = link:gsub(
'|' .. gamePattern .. '%s+',
'|'
)
end
return results
end
local function renameLabels(results)
local labels = {
Mods = 'Mod Archive',
Players = 'Player Roster',
Clans = 'Clan History',
}
for i, link in ipairs(results) do
results[i] = link:gsub('|([^%]]+)%]%]', function(label)
return '|' .. (labels[label] or label) .. ']]'
end)
end
return results
end
local function sortSubpages(results)
local order = {
Mods = 1,
Players = 2,
Clans = 3,
}
table.sort(results, function(a, b)
-- Extract the final subpage name from the link target.
local targetA = a:match('^%[%[:.-/([^/|%]]+)|')
local targetB = b:match('^%[%[:.-/([^/|%]]+)|')
local rankA = order[targetA] or math.huge
local rankB = order[targetB] or math.huge
if rankA ~= rankB then
return rankA < rankB
end
-- Keep all remaining subpages alphabetically ordered.
return (targetA or a) < (targetB or b)
end)
return results
end
local function getSubpages(page)
local subpages = mw.smw.ask({
'[[Has parent page::' .. page .. ']][[Modification date::+]]'
}) or {}
local subpageTable = {}
for _, subpage in ipairs(subpages) do
local link = subpage[1]
if link then
table.insert(subpageTable, link)
end
end
local allGames = string.format('[[%s|%s]]', 'Games', 'All Games')
table.insert(subpageTable, allGames)
removeGameFromLabels(subpageTable, page)
renameLabels(subpageTable)
sortSubpages(subpageTable)
if #subpageTable == 0 then
return ''
end
local html = mw.html.create()
local universe = html:tag('div'):attr('id', 'universeMenu'):wikitext(' | ' .. table.concat(subpageTable, ' | '))
return tostring(html)
end
local function formatCellValue(value)
if value == nil then
return ''
end
if type(value) == 'table' then
local values = {}
for _, item in ipairs(value) do
table.insert(values, tostring(item))
end
return table.concat(values, '<br>')
end
return tostring(value)
end
local function renderModTable(content)
local wrapper = mw.html.create('div')
wrapper
:attr('id', 'assets')
local tableNode = wrapper:tag('table')
tableNode
:addClass('wikitable')
:addClass('sortable')
local header = tableNode:tag('tr')
header:tag('th'):wikitext('Game')
header:tag('th'):wikitext('Asset')
header:tag('th'):wikitext('Type')
header:tag('th'):wikitext('Subtype')
header:tag('th'):wikitext('Mode')
header:tag('th'):wikitext('Developer')
header:tag('th'):wikitext('Released')
header:tag('th'):wikitext('Status')
header:tag('th'):wikitext('Description')
header:tag('th'):wikitext('Version')
header:tag('th'):wikitext('Files')
for _, row in ipairs(content or {}) do
local tr = tableNode:tag('tr')
tr:tag('td'):wikitext(formatCellValue(row[1]))
tr:tag('td'):wikitext(formatCellValue(row['Category']))
tr:tag('td'):wikitext(
formatCellValue(row['Has map type'])
, formatCellValue(row['Has skin type'])
, formatCellValue(row['Has mod type'])
, formatCellValue(row['Has utility type'])
)
tr:tag('td'):wikitext(formatCellValue(row['Has game mode']))
tr:tag('td'):wikitext(formatCellValue(row['Has developer']))
tr:tag('td'):wikitext(formatCellValue(row['Has release date']))
tr:tag('td'):wikitext(formatCellValue(row['Has status']))
tr:tag('td'):wikitext(formatCellValue(row['Has short description']))
tr:tag('td'):wikitext(formatCellValue(row['Works on game version']))
tr:tag('td'):wikitext(formatCellValue(row['Download links']))
tr:tag('td'):wikitext(formatCellValue(row['Related game']))
end
return wrapper
end
local function renderPlayerTable(content)
local wrapper = mw.html.create('div')
wrapper
:attr('id', 'players')
local tableNode = wrapper:tag('table')
tableNode
:addClass('wikitable')
:addClass('sortable')
local header = tableNode:tag('tr')
header:tag('th'):wikitext('Player Name')
header:tag('th'):wikitext('Games')
header:tag('th'):wikitext('Clans')
header:tag('th'):wikitext('Roles')
header:tag('th'):wikitext('Clan (Role)')
for _, row in ipairs(content or {}) do
local clanValues = {}
local roleValues = {}
local clanAndRoleValues = {}
local member = row['Member of']
if member then
-- SMW may return either one value or a table of values.
local memberships = type(member) == 'table'
and member
or { member }
for _, clan in ipairs(memberships) do
local formattedClan = formatCellValue(clan)
table.insert(
clanValues,
string.format('<div>%s</div>', formattedClan)
)
local query = {
'[[-Has subobject::' .. row[1] .. ']]',
'[[Member of::' .. clan .. ']]',
'?Has role#-=role',
mainlabel = '-',
}
local results = mw.smw.ask(query)
local clanRoles = {}
local function addRoles(value)
if value == nil or value == '' then
return
end
for role in mw.text.gsplit(tostring(value), ',', true) do
role = mw.text.trim(role)
if role ~= '' then
table.insert(
clanRoles,
formatCellValue(role)
)
end
end
end
for _, resultRow in ipairs(results or {}) do
local resultRoles = resultRow.role
if type(resultRoles) == 'table' then
for _, roleValue in ipairs(resultRoles) do
addRoles(roleValue)
end
else
addRoles(resultRoles)
end
end
if #clanRoles > 0 then
local roleDivs =
'<div>' ..
table.concat(clanRoles, '</div><div>') ..
'</div>'
table.insert(roleValues, roleDivs)
table.insert(
clanAndRoleValues,
string.format(
'<div>%s (%s)</div>',
formattedClan,
table.concat(clanRoles, ', ')
)
)
else
table.insert(roleValues, '<div>—</div>')
table.insert(
clanAndRoleValues,
string.format('<div>%s</div>', formattedClan)
)
end
end
end
local tr = tableNode:tag('tr')
tr:tag('td'):wikitext(formatCellValue(row[1]))
tr:tag('td'):wikitext(formatCellValue(row['Plays game']))
tr:tag('td'):wikitext(table.concat(clanValues, ''))
tr:tag('td'):wikitext(table.concat(roleValues, ''))
tr:tag('td'):wikitext(table.concat(clanAndRoleValues, ''))
tr:tag('td'):wikitext(formatCellValue(row['Has status']))
end
return wrapper
end
function p.Mods(frame)
local data = getCurrentGame()
local game = data.game or '+'
local resource = data.resource
mw.smw.set({
['Has parent page'] = game
})
local query = {
'[[Category:Mods||Maps||Skins||Utilities]][[Related game::' .. game .. ']]',
'?Related game',
'?Category',
'?Has mod type',
'?Has map type',
'?Has skin type',
'?Has utility type',
'?Has game mode',
'?Has developer',
'?Has release date#-F[Y]',
'?Has status',
'?Has short description',
'?Works on game version',
'?Download links'
}
local content = mw.smw.ask(query)
local forminput = frame:callParserFunction({ name = '#forminput', '', args = {
'form=Mod',
'query string=Mod[Related game]=' .. game,
'button text=Create or Edit Mod',
'autofocus=no'
}})
setDisplayTitle(frame, string.format('%s %s', game, resource))
local html = mw.html.create()
html:wikitext(getSubpages(game))
html:wikitext(forminput)
html:node(renderModTable(content))
return html
end
function p.allMods(frame)
local query = {
'[[Category:Mods||Maps||Skins||Utilities]][[Related game::+]]',
'?Related game',
'?Category',
'?Has mod type',
'?Has map type',
'?Has skin type',
'?Has utility type',
'?Has game mode',
'?Has developer',
'?Has release date#-F[Y]',
'?Has status',
'?Has short description',
'?Works on game version',
'?Download links'
}
local content = mw.smw.ask(query)
local html = mw.html.create()
html:node(renderModTable(content, true))
return html
end
function p.Players(frame)
local data = getCurrentGame()
local game = data.game
local resource = data.resource
mw.smw.set({
['Has parent page'] = game
})
local query = {
'[[Category:Players]][[Plays game::' .. game .. ']]',
'?Plays game',
'?Member of',
'?Has status'
}
local content = mw.smw.ask(query)
local forminput = frame:callParserFunction({ name = '#forminput', '', args = {
'form=Player',
'query string=Player[Plays game]=' .. game,
'button text=Create or Edit Player Entry',
'autocomplete on category=Players',
'autofocus=no'
}})
setDisplayTitle(frame, string.format('%s %s', game, resource))
local html = mw.html.create()
html:wikitext(getSubpages(game))
html:wikitext(forminput)
html:node(renderPlayerTable(content))
return html
end
function p.allPlayers(frame)
local query = {
'[[Category:Players]][[Plays game::+]]',
'?Plays game',
'?Member of',
'?Has status'
}
local content = mw.smw.ask(query)
local html = mw.html.create()
html:node(renderPlayerTable(content))
return html
end
function p.clanPlayers(frame)
local title = mw.title.getCurrentTitle()
local clan = title.fullText
local query = {
'[[-Member of::' .. clan .. ']]',
}
local content = mw.smw.ask(query)
local html = mw.html.create()
html:node(renderPlayerTable(content))
return html
end
function p.Clans(frame)
local data = getCurrentGame()
local game = data.game
local resource = data.resource
mw.smw.set({
['Has parent page'] = game
})
local query = {
'[[Category:Communities]][[Related game::' .. game .. ']]'
}
local content = mw.smw.ask(query)
local forminput = frame:callParserFunction({ name = '#forminput', '', args = {
'form=Community',
'query string=Community[Related game]=' .. game,
'button text=Create or Edit Community Entry',
'autocomplete on category=Communities',
'autofocus=no'
}})
setDisplayTitle(frame, string.format('%s %s', game, resource))
local html = mw.html.create()
html:wikitext(getSubpages(game))
html:wikitext(forminput)
return html
end
return p
