Module:InfoboxResearch: Difference between revisions
Jump to navigation
Jump to search
Research display module and templates |
Research display module and templates |
||
| (One intermediate revision by the same user not shown) | |||
| Line 12: | Line 12: | ||
end | end | ||
return nil | return nil | ||
end | |||
-- mw.loadData hands back a proxy table: ipairs and pairs work on it, the # operator does not. | |||
local function count(tbl) | |||
if not tbl then | |||
return 0 | |||
end | |||
local n = 0 | |||
for _ in ipairs(tbl) do | |||
n = n + 1 | |||
end | |||
return n | |||
end | end | ||
| Line 38: | Line 50: | ||
end | end | ||
return splitCamelCase(name) | return splitCamelCase(name) | ||
end | |||
local function requireLink(req) | |||
local text = researchLink(req.name) | |||
if req.level then | |||
text = text .. ' level ' .. tostring(req.level) | |||
end | |||
return text | |||
end | end | ||
| Line 73: | Line 93: | ||
local total = 0 | local total = 0 | ||
for _, level in ipairs(data.levels or {}) do | for _, level in ipairs(data.levels or {}) do | ||
total = total + | total = total + count(level.unlocks) | ||
end | end | ||
return total | return total | ||
| Line 102: | Line 122: | ||
table.insert(out, '| ' .. tostring(data.tier)) | table.insert(out, '| ' .. tostring(data.tier)) | ||
local levelCount = count(data.levels) | |||
if levelCount > 1 then | |||
table.insert(out, '|-') | table.insert(out, '|-') | ||
table.insert(out, '! Levels') | table.insert(out, '! Levels') | ||
table.insert(out, '| ' .. tostring( | table.insert(out, '| ' .. tostring(levelCount)) | ||
end | end | ||
| Line 123: | Line 144: | ||
local requires = data.levels[1].requires | local requires = data.levels[1].requires | ||
if requires | if count(requires) > 0 then | ||
local links = {} | local links = {} | ||
for _, req in ipairs(requires) do | for _, req in ipairs(requires) do | ||
table.insert(links, | table.insert(links, requireLink(req)) | ||
end | end | ||
table.insert(out, '|-') | table.insert(out, '|-') | ||
| Line 176: | Line 197: | ||
local function renderLevels(data) | local function renderLevels(data) | ||
if | if count(data.levels) < 2 then | ||
return nil | return nil | ||
end | end | ||
| Line 185: | Line 206: | ||
local links = {} | local links = {} | ||
for _, req in ipairs(level.requires or {}) do | for _, req in ipairs(level.requires or {}) do | ||
table.insert(links, | table.insert(links, requireLink(req)) | ||
end | end | ||
table.insert(out, '|-') | table.insert(out, '|-') | ||
| Line 218: | Line 239: | ||
if effect then | if effect then | ||
table.insert(out, '== Effect ==') | table.insert(out, '== Effect ==') | ||
table.insert(out, effect .. ', over ' .. tostring( | table.insert(out, effect .. ', over ' .. tostring(count(data.levels)) .. ' levels.') | ||
end | end | ||
| Line 228: | Line 249: | ||
end | end | ||
if data.leads_to | if count(data.leads_to) > 0 then | ||
local links = {} | local links = {} | ||
for _, follower in ipairs(data.leads_to) do | for _, follower in ipairs(data.leads_to) do | ||
Latest revision as of 12:52, 10 September 2026
Documentation for this module may be created at Module:InfoboxResearch/doc
-- Module:InfoboxResearch
-- Renders the research pages from Module:Data/Research/*, which
-- wiki/generate_researches.py writes out of Content/Generated/Researches.
local p = {}
local DATA = 'Module:Data/Research/'
local function load(name)
local ok, data = pcall(mw.loadData, DATA .. name)
if ok and type(data) == 'table' then
return data
end
return nil
end
-- mw.loadData hands back a proxy table: ipairs and pairs work on it, the # operator does not.
local function count(tbl)
if not tbl then
return 0
end
local n = 0
for _ in ipairs(tbl) do
n = n + 1
end
return n
end
local function splitCamelCase(str)
str = str:gsub('_', ' ')
str = str:gsub('(%l)(%u)', '%1 %2')
str = str:gsub('(%a)(%d)', '%1 %2')
str = str:gsub('(%d)(%a)', '%1 %2')
return str
end
local function thousands(n)
local digits = string.format('%d', n)
local out = digits:reverse():gsub('(%d%d%d)', '%1 '):reverse()
return (out:gsub('^%s+', ''))
end
local function pageTitle(row)
return row.title or (row.label .. ' (research)')
end
local function researchLink(name)
local data = load(name)
if data then
return string.format('[[%s|%s]]', pageTitle(data), data.label)
end
return splitCamelCase(name)
end
local function requireLink(req)
local text = researchLink(req.name)
if req.level then
text = text .. ' level ' .. tostring(req.level)
end
return text
end
local function itemLink(item)
return string.format('[[File:T_%s.png|22px|link=%s]] [[%s]]',
item, splitCamelCase(item), splitCamelCase(item))
end
local function unlockCell(unlock)
if unlock.item then
return itemLink(unlock.item)
end
return splitCamelCase(unlock.recipe)
end
local function icon(data, size)
if not data.icon then
return ''
end
return string.format('[[File:T_%s.png|%dpx]]', data.icon, size)
end
local function effectLine(data)
if data.kind == 'modifier' then
return string.format('+%d%% %s per level', data.bonus or 0,
splitCamelCase(data.modifier or ''))
end
if data.kind == 'bonusinventory' then
return string.format('+%d inventory slots per level', data.slots or 0)
end
return nil
end
local function countUnlocks(data)
local total = 0
for _, level in ipairs(data.levels or {}) do
total = total + count(level.unlocks)
end
return total
end
function p.show(frame)
local name = frame.args[1]
if not name or name == '' then
return '❌ No research name provided'
end
local data = load(name)
if not data then
return '❌ No data module for ' .. name
end
local out = {}
table.insert(out, '{| class="infobox"')
table.insert(out, '|-')
table.insert(out, '| colspan="2" style="text-align:center;" | ' ..
icon(data, 64) .. " '''" .. data.label .. "'''")
table.insert(out, '|-')
table.insert(out, '! Science')
table.insert(out, '| ' .. thousands(data.levels[1].science))
table.insert(out, '|-')
table.insert(out, '! Tier')
table.insert(out, '| ' .. tostring(data.tier))
local levelCount = count(data.levels)
if levelCount > 1 then
table.insert(out, '|-')
table.insert(out, '! Levels')
table.insert(out, '| ' .. tostring(levelCount))
end
local effect = effectLine(data)
if effect then
table.insert(out, '|-')
table.insert(out, '! Effect')
table.insert(out, '| ' .. effect)
end
local unlocks = countUnlocks(data)
if unlocks > 0 then
table.insert(out, '|-')
table.insert(out, '! Recipes')
table.insert(out, '| ' .. tostring(unlocks))
end
local requires = data.levels[1].requires
if count(requires) > 0 then
local links = {}
for _, req in ipairs(requires) do
table.insert(links, requireLink(req))
end
table.insert(out, '|-')
table.insert(out, '! Requires')
table.insert(out, '| ' .. table.concat(links, '<br />'))
end
table.insert(out, '|-')
table.insert(out, '! Internal name')
table.insert(out, '| <code>' .. data.name .. '</code>')
table.insert(out, '|}')
return table.concat(out, '\n')
end
local function renderUnlocks(data)
local out = {}
local byMachine = {}
local order = {}
for _, level in ipairs(data.levels) do
for _, unlock in ipairs(level.unlocks or {}) do
if not byMachine[unlock.machine] then
byMachine[unlock.machine] = {}
table.insert(order, unlock.machine)
end
table.insert(byMachine[unlock.machine], unlock)
end
end
if #order == 0 then
return nil
end
table.sort(order)
table.insert(out, '{| class="wikitable"')
table.insert(out, '! Made in !! Recipe')
for _, machine in ipairs(order) do
local cells = {}
for _, unlock in ipairs(byMachine[machine]) do
table.insert(cells, unlockCell(unlock))
end
local made = machine == 'Hand' and 'Hand crafting'
or string.format('[[%s]]', splitCamelCase(machine))
table.insert(out, '|-')
table.insert(out, '| ' .. made .. ' || ' .. table.concat(cells, ' · '))
end
table.insert(out, '|}')
return table.concat(out, '\n')
end
local function renderLevels(data)
if count(data.levels) < 2 then
return nil
end
local out = {}
table.insert(out, '{| class="wikitable"')
table.insert(out, '! Level !! Science !! Also requires')
for _, level in ipairs(data.levels) do
local links = {}
for _, req in ipairs(level.requires or {}) do
table.insert(links, requireLink(req))
end
table.insert(out, '|-')
table.insert(out, string.format('| %d || %s || %s',
level.level,
thousands(level.science),
#links > 0 and table.concat(links, ', ') or '—'))
end
table.insert(out, '|}')
return table.concat(out, '\n')
end
function p.data(frame)
local name = frame.args[1]
if not name or name == '' then
return '❌ No research name provided'
end
local data = load(name)
if not data then
return '❌ No data module for ' .. name
end
local out = {}
local unlocks = renderUnlocks(data)
if unlocks then
table.insert(out, '== Unlocks ==')
table.insert(out, unlocks)
end
local effect = effectLine(data)
if effect then
table.insert(out, '== Effect ==')
table.insert(out, effect .. ', over ' .. tostring(count(data.levels)) .. ' levels.')
end
local levels = renderLevels(data)
if levels then
table.insert(out, '== Levels ==')
table.insert(out, 'The levels past the first are hidden until the one before it is done.')
table.insert(out, levels)
end
if count(data.leads_to) > 0 then
local links = {}
for _, follower in ipairs(data.leads_to) do
table.insert(links, researchLink(follower))
end
table.sort(links)
table.insert(out, '== Leads to ==')
table.insert(out, table.concat(links, ' · '))
end
return table.concat(out, '\n\n')
end
function p.index(frame)
local ok, index = pcall(mw.loadData, DATA .. 'Index')
if not ok or type(index) ~= 'table' then
return '❌ No research index'
end
local byTier = {}
local tiers = {}
for _, row in ipairs(index.researches or {}) do
if not byTier[row.tier] then
byTier[row.tier] = {}
table.insert(tiers, row.tier)
end
table.insert(byTier[row.tier], row)
end
table.sort(tiers)
local out = {}
for _, tier in ipairs(tiers) do
table.insert(out, '=== Tier ' .. tostring(tier) .. ' ===')
table.insert(out, '{| class="wikitable sortable"')
table.insert(out, '! !! Research !! Science !! Levels !! Effect')
for _, row in ipairs(byTier[tier]) do
local img = row.icon and string.format('[[File:T_%s.png|22px]]', row.icon) or ''
local kind = row.kind == 'modifier' and 'Modifier'
or row.kind == 'bonusinventory' and 'Inventory slots'
or 'Recipes'
table.insert(out, '|-')
table.insert(out, string.format('| %s || [[%s|%s]] || %s || %s || %s',
img, pageTitle(row), row.label, thousands(row.science),
tostring(row.levels), kind))
end
table.insert(out, '|}')
end
return table.concat(out, '\n')
end
return p