Module:Crafting usage: Difference between revisions
Mastergalen (talk | contribs) No edit summary |
Mastergalen (talk | contribs) No edit summary |
||
Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
function p.dpl( f ) | 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 | end | ||
return p | return p |
Revision as of 17:48, 10 July 2015
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