More actions
This module creates the table for {{crafting}}
, {{brewing}}
, {{smelting}}
and {{looming}}
. It can only be invoked within other modules.
Usage
The entry point is the table
function. The first argument should be whatever arguments you want to pass through, the second argument should be a table of settings.
Setting | Use |
---|---|
type | What type of recipe, e.g.: 'Crafting'
|
ingredientArgs | A table of the args which contain the ingredients, e.g.: { 'Input' }
|
outputArgs | A table of the args which contain the outputs, e.g.: { 'Output' }
|
uiFunc | The function to call from Module:UI, e.g.: 'craftingTable'
|
The module returns the wikitext table as the first parameter, and a table of unique ingredients as the second output.
Dependencies
es:Módulo:Recipe table
fr:Module:Tableau de recette
ja:モジュール:Recipe table
pt:Módulo:Recipe table
ru:Модуль:Таблица рецептов
uk:Модуль:Recipe table
local m = {}
local i18n = {
headingDescription = 'Description',
headingIngredients = 'Ingredients',
headingName = 'Name',
headingRecipe = '[[$1]] recipe',
moduleSlot = [[Module:Inventory slot]],
moduleUi = [[Module:UI]],
separator = ' +',
setSeparator = ' or',
tableDescription = '$1 recipes',
}
local slot = require( i18n.moduleSlot )
local prefixes = slot.i18n.prefixes
--[[Merges a list, or inserts a string
or table into a table
--]]
local function mergeList( parentTable, content )
local i = #parentTable + 1
if content[1] then
-- Merge list into table
for _, v in ipairs( content ) do
parentTable[i] = v
i = i + 1
end
else
-- Add strings or tables to table
parentTable[i] = content
end
end
--[[Loops through the input and output args and parses them into a single table,
with alias reference data
Identical slots reuse the same table, to allow them to be compared like strings
--]]
local function parseRecipeArgs( args, ingredientArgVals, outputArgs )
local recipeArgs = {}
for _, arg in pairs( ingredientArgVals ) do
recipeArgs[arg] = args[arg]
end
for _, arg in pairs( outputArgs ) do
recipeArgs[arg] = args[arg]
end
local parsedFrameText = {}
local parsedRecipeArgs = {}
for arg, frameText in pairs( recipeArgs ) do
if frameText then
local randomise
for _, oArg in pairs( outputArgs ) do
if arg == oArg then
randomise = 'never'
break
end
end
local frames = not randomise and parsedFrameText[frameText]
if not frames then
frames = slot.parseFrameText( frameText, randomise, true )
parsedFrameText[frameText] = frames
end
parsedRecipeArgs[arg] = frames
end
end
return parsedRecipeArgs
end
--[[Creates a link (with mod name if specified) with
any prefix moved outside
--]]
function m.prefixedLink( name, mod )
local prefix = ''
for _, thisPrefix in pairs( prefixes ) do
if name:find( '^' .. thisPrefix .. ' ' ) then
prefix = thisPrefix .. ' '
name = name:sub( #prefix + 1 )
if name:find( '^' .. prefixes.unwaxed .. ' ' ) then
prefix = prefix .. prefixes.unwaxed .. ' '
name = name:sub( #prefixes.unwaxed + 1 )
end
break
end
end
local page = name
if mod then
page = slot.i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name )
end
return table.concat{ prefix, '[[', page, '|', name, ']]' }
end
--[[Creates sets of unique items from a set of slots, using the
original alias name if available
Each set of items are the frames of that slot
--]]
function m.makeItemSets( argVals, parsedArgs )
local usedItems = {}
local function addItem( items, arg, frame, alias )
if alias then
frame = alias.frame
end
local uniqName = ( frame.mod or '' ) .. ':' .. frame.name
if not usedItems[uniqName] then
usedItems[uniqName] = true
items[#items + 1] = frame
end
return alias and alias.length or 1
end
local itemSets = {}
local i = 1
for _, arg in ipairs( argVals ) do
local frames = parsedArgs[arg]
if frames then
local items = {}
local frameNum = 1
while frameNum <= #frames do
local frame = frames[frameNum]
if frame[1] then
local subframeNum = 1
while subframeNum <= #frame do
local subframe = frame[subframeNum]
if subframe.name ~= '' then
local alias = frame.aliasReference and frame.aliasReference[subframeNum]
subframeNum = subframeNum + addItem( items, arg, subframe, alias )
else
subframeNum = subframeNum + 1
end
end
frameNum = frameNum + 1
elseif frame.name ~= '' then
local alias = frames.aliasReference and frames.aliasReference[frameNum]
frameNum = frameNum + addItem( items, arg, frame, alias )
else
frameNum = frameNum + 1
end
end
if #items > 0 then
itemSets[i] = items
i = i + 1
end
end
end
return itemSets
end
--[[Creates links for the name/ingredients columns out of
item sets, with the appropriate separators, and optionally
"Any" and "Matching" prefixes removed.
--]]
function m.makeItemLinks( itemSets, removePrefixes )
local links = {}
for i, itemSet in ipairs( itemSets ) do
local linkSet = {}
for i2, item in ipairs( itemSet ) do
local name = item.name
if removePrefixes then
-- Remove prefixes and uppercase first letter
name = name
:gsub( '^' .. prefixes.any .. ' ', '' )
:gsub( '^' .. prefixes.matching .. ' ', '' )
:gsub( '^%l', string.upper )
end
local disjunctionA, disjunctionB = name:match("(.-) or (.+)") -- hardcoding "A or B" names in English
if disjunctionA then
linkSet[i2] = m.prefixedLink( disjunctionA, item.mod )
.. ' or '
.. m.prefixedLink( disjunctionB, item.mod )
else
linkSet[i2] = m.prefixedLink( name, item.mod )
end
end
links[i] = table.concat( linkSet, i18n.setSeparator .. '<br>' )
end
return table.concat( links, i18n.separator .. '<br>' )
end
-- Creates the table header
function m.makeHeader( recipeType, class, showName, showDescription, multirow )
class = class or ''
local nameCell = ''
if showName then
nameCell = i18n.headingName .. '!!'
end
local descriptionCell = ''
if showDescription then
descriptionCell = '!!class="unsortable"|' .. i18n.headingDescription
end
local recipeAttribs = ''
if multirow then
class = 'sortable ' .. class
recipeAttribs = 'class="unsortable"|'
end
local header = table.concat( {
' {| class="wikitable collapsible ' .. class .. '" data-description="' .. i18n.tableDescription:gsub( '%$1', recipeType ) .. '"',
'!' .. nameCell ..
i18n.headingIngredients .. '!!' ..
recipeAttribs .. i18n.headingRecipe:gsub( '%$1', recipeType ) ..
descriptionCell
}, '\n' )
return header
end
-- Create the contents for the name cell
function m.makeNameCell( name, itemSets )
local cell = {}
if name then
cell[1] = name
else
cell[1] = m.makeItemLinks( itemSets, true )
end
return table.concat( cell, '<br>' )
end
-- Create the contents for the ingredients cell
function m.makeIngredientsCell( ingredients, itemSets )
return ingredients or m.makeItemLinks( itemSets )
end
--[[Main entry point, creates the table with the relevant DPL vars
to allow multiple table rows from separate template calls
Also returns the unique ingredients, for categorisation purposes in
Module:Crafting
--]]
function m.table( args, settings )
local f = mw.getCurrentFrame()
local multirow = f:callParserFunction( '#dplvar', 'recipetable-multirow' )
if multirow == '' then
multirow = nil
end
local showHead = args.head
local showFoot = args.foot
if multirow then
showHead = nil
elseif showHead and not showFoot then
multirow = true
f:callParserFunction( '#dplvar:set', 'recipetable-multirow', '1' )
else
showHead = true
showFoot = true
end
local showName = args.showname
local showDescription = args.showdescription
if multirow then
if showHead then
showName = args.showname or '1'
f:callParserFunction( '#dplvar:set', 'recipetable-name', showName, 'recipetable-description', showDescription )
else
showName = f:callParserFunction( '#dplvar', 'recipetable-name' )
showDescription = f:callParserFunction( '#dplvar', 'recipetable-description' )
end
end
if showName ~= '1' then
showName = nil
end
if showDescription == '' then
showDescription = nil
end
local out = {}
if showHead then
out[1] = m.makeHeader( settings.type, args.class, showName, showDescription, multirow )
end
local ingredientArgVals = settings.ingredientArgs
local outputArgs = settings.outputArgs
local parsedRecipeArgs = args
if not args.parsed then
parsedRecipeArgs = parseRecipeArgs( args, ingredientArgVals, outputArgs )
end
local cells = {}
local outputItemSets = m.makeItemSets( outputArgs, parsedRecipeArgs )
if showName then
cells[1] = '!' .. m.makeNameCell( args.name, outputItemSets )
end
local ingredientsItemSets = m.makeItemSets( ingredientArgVals, parsedRecipeArgs )
cells[#cells + 1] = '|' .. m.makeIngredientsCell( args.ingredients, ingredientsItemSets )
cells[#cells + 1] = '|style="padding:1px;text-align:center"|' .. require( i18n.moduleUi )[settings.uiFunc]( args )
if showDescription then
cells[#cells + 1] = '|' .. ( args.description or '' )
end
out[#out + 1] = table.concat( cells, '\n' )
out[#out + 1] = showFoot and '|}' or ''
if showFoot then
f:callParserFunction( '#dplvar:set',
'recipetable-multirow', '',
'recipetable-name', '',
'recipetable-description', ''
)
end
return table.concat( out, '\n|-\n' ), ingredientsItemSets, outputItemSets
end
return m