Module:Crafting usage
This module implements {{Crafting usage}}.
Dependencies
The above documentation is transcluded from Module:Crafting usage/doc.
This module implements {{Crafting usage}}.
Dependencies
local p = {}
function p.dpl( f )
local args = f:getParent().args
local grid = require( 'Module:Grid' )
local ingredients = args[1] and mw.text.split( args[1], '%s*,%s*' ) or { mw.title.getCurrentTitle().text }
local matchTypes = args.match and args.match:find( ',' ) and mw.text.split( args.match, '%s*,%s*' ) or args.match
local argList = {
'ignoreusage', 'upcoming', 'name', 'ingredients', 'arggroups',
1, 2, 3, 4, 5, 6, 7, 8, 9,
'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3',
'Output', 'description', 'fixed', 'notfixed'
}
local anonToShaped = { 'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3' }
local shapedToAnon = { A1 = 1, B1 = 2, C1 = 3, A2 = 4, B2 = 5, C2 = 5, A3 = 6, B3 = 7, C3 = 8 }
local data = ''
if args.category then
data = f:callParserFunction( '#dpl', {
category = args.category,
nottitleregexp = args.ignore,
include = '{Crafting}:' .. table.concat( argList, ':' ),
mode = 'userformat',
secseparators = '====',
multisecseparators = '===='
} )
else
-- #dpl has a limit of four, so do it in chunks of 4
for i = 1, #ingredients, 4 do
data = data .. f:callParserFunction( '#dpl', {
"category=" .. 'Recipe using ' .. table.concat( ingredients, '|Recipe using ', i, math.min( i + 3, #ingredients ) ),
"nottitleregexp=" .. args.ignore,
"include=" .. '{Crafting}:' .. table.concat( argList, ':' ),
"mode=" .. 'userformat',
"secseparators=" .. '====',
"multisecseparators=" .. '====',
})
end
end
-- Comment this next line out if you're not using aliases
local aliases = mw.loadData( 'Module:Grid/Aliases' )
local function matchPattern( ingredient, ingredientNum )
local matchType = matchTypes
if type( matchType ) == 'table' then
matchType = matchTypes[ingredientNum]
end
local pattern
local escaped = ingredient:gsub( '([%(%)])', '%%%1' )
if matchType == 'start' then
pattern = '[;:%]]%s*' .. escaped
elseif matchType == 'end' then
pattern = escaped .. '%s*[,;%[]'
elseif matchType == 'any' then
pattern = escaped
else
pattern = '[;:%]]%s*' .. escaped .. '%s*[,;%[]'
end
return pattern
end
local function compareTables( a, b )
for k, v in pairs( a ) do
if type( b[k] ) ~= type( v ) then
return false
end
if type( v ) == 'table' then
if not compareTables( v, b[k] ) then
return false
end
elseif v ~= b[k] then
return false
end
end
for k, v in pairs( b ) do
if a[k] == nil then
return false
end
end
return true
end
local out = {}
local showDesciption
local templates = {}
for template in mw.text.gsplit( data, '====' ) do
-- If ignoreusage is empty
if template:find( '^%s*|' ) then
local tArgs = {}
local i = 0
-- Extract the arguments from the DPL query
for tArg in mw.text.gsplit( template, '\n|' ) do
i = i + 1
if tArg ~= '' then
local key = argList[i]
tArgs[key] = tArg
end
end
local craftingArgs = {
tArgs[1] or tArgs.A1 or '', tArgs[2] or tArgs.B1 or '', tArgs[3] or tArgs.C1 or '',
tArgs[4] or tArgs.A2 or '', tArgs[5] or tArgs.B2 or '', tArgs[6] or tArgs.C2 or '',
tArgs[7] or tArgs.A3 or '', tArgs[8] or tArgs.B3 or '', tArgs[9] or tArgs.C3 or '',
Output = tArgs.Output
}
local expandedFrames = {}
local hasIngredient
local argsWithIngredient = {}
local argGroups = {}
for i, v in pairs( craftingArgs ) do
if v ~= '' then
if aliases then
expandedFrames[i] = {}
local expandedFrame = {}
for frame in mw.text.gsplit( v, '%s*;%s*' ) do
local parts = grid.getParts( frame )
local alias = aliases[parts.name]
if alias then
local expandedAlias = grid.expandAlias( parts, alias ):gsub( '%s*([%[%]:,;])%s*', '%1' )
expandedFrames[i][frame] = expandedAlias:gsub( '([%(%)])', '%%%1' )
table.insert( expandedFrame, expandedAlias )
else
table.insert( expandedFrame, frame )
end
end
v = table.concat( expandedFrame, ';' )
craftingArgs[i] = v
end
if i ~= 'Output' then
local delimitedFrames = ';' .. v .. ';'
for ingredientNum, ingredient in pairs( ingredients ) do
if delimitedFrames:find( matchPattern( ingredient, ingredientNum ) ) then
if not v:find( ';' ) then
hasIngredient = 'static'
elseif not hasIngredient then
hasIngredient = 'animated'
end
argsWithIngredient[i] = true
end
end
end
if not tArgs.arggroups and hasIngredient ~= 'static' then
local _, frameCount = v:gsub( ';', '' )
if frameCount > 0 then
frameCount = frameCount + 1
local group = argGroups[frameCount]
if not group then
group = { args = {} }
argGroups[frameCount] = group
end
group.count = frameCount
group.args[i] = true
end
end
end
end
if hasIngredient then
if tArgs.description then
showDescription = true
end
if hasIngredient == 'animated' then
if tArgs.arggroups then
for argGroup in mw.text.gsplit( tArgs.arggroups, '%s*;%s*' ) do
local group = {}
local _, frameCount
for arg in mw.text.gsplit( argGroup, '%s*,%s*' ) do
if not tArgs[1] then
arg = shapedToAnon[arg]
end
if not frameCount then
_, frameCount = craftingArgs[arg]:gsub( ';', '' )
end
group[arg] = true
end
table.insert( argGroups, { count = frameCount + 1, args = group } )
end
end
for _, groupData in pairs( argGroups ) do
local frameCount = groupData.count
local group = groupData.args
local requiredFrames = {}
local requiredFramesCount = 0
for arg in pairs( group ) do
if argsWithIngredient[arg] then
local frames = craftingArgs[arg]
local frameNum = 0
for frame in mw.text.gsplit( frames, '%s*;%s*' ) do
frameNum = frameNum + 1
if not requiredFrames[frameNum] then
local delimitedFrame = ';' .. frame .. ';'
for ingredientNum, ingredient in pairs( ingredients ) do
if delimitedFrame:find( matchPattern( ingredient, ingredientNum ) ) then
requiredFrames[frameNum] = true
requiredFramesCount = requiredFramesCount + 1
end
end
end
end
end
end
-- Not all frames will be used
if requiredFramesCount > 0 and requiredFramesCount < frameCount then
for arg in pairs( group ) do
local frames = craftingArgs[arg]
local newFrames = {}
local frameNum = 0
for frame in mw.text.gsplit( frames, '%s*;%s*' ) do
frameNum = frameNum + 1
if requiredFrames[frameNum] then
table.insert( newFrames, frame )
end
end
newFrames = table.concat( newFrames, ';' )
-- If the whole expanded alias survived, collapse it again
if expandedFrames[arg] then
for frame, expandedAlias in pairs( expandedFrames[arg] ) do
--newFrames = 'blah' .. expandedAlias
newFrames = newFrames:gsub( expandedAlias, frame )
end
end
local tArg = arg
if arg ~= 'Output' and not tArgs[1] then
tArg = anonToShaped[arg]
end
tArgs[tArg] = newFrames
end
-- Let Module:Crafting handle the name and ingredients columns
tArgs.name = nil
tArgs.ingredients = nil
end
end
end
tArgs.nocat = '1'
local found = false
for i, v in ipairs( templates ) do
if compareTables( v, tArgs ) then
found = true
break
end
end
if not found then
table.insert( templates, tArgs )
end
end
end
end
if #templates == 0 then
return '[[Category:Empty crafting usage]]'
end
templates[1].head = '1'
templates[1].showname = '1'
if showDescription and args.showdesciption ~= '0' or args.showdesciption == '1' then
templates[1].showdescription = '1'
end
if not args.continue then
templates[#templates].foot = '1'
end
local crafting = require( 'Module:Crafting' )
local out = {}
for i, v in ipairs( templates ) do
table.insert( out, crafting.table( v ) )
end
return table.concat( out, '\n' )
end
return p