Модуль:Использование для крафта
Внешний вид
Для документации этого модуля может быть создана страница Модуль:Использование для крафта/doc
-- Модуль для отображения списка рецептов крафта, в котором тот или иной предмет используется.
local p = {}
local slot = require("Модуль:Инвентарный слот")
local splitOnUnenclosedSemicolons = slot.splitOnUnenclosedSemicolons
function p.dpl( f )
local args = f:getParent().args
local ingredients = args[1] and mw.text.split( args[1], '%s*,%s*' ) or { mw.title.getCurrentTitle().text }
local matchTypes = args["фрагмент"] and mw.ustring.find(args["фрагмент"], ',' ) and mw.text.split( args["фрагмент"], '%s*,%s*' ) or args["фрагмент"]
local argList = {
'игнорировать', 'запланированное', 'имя', 'ингредиенты', 'группыарг',
1, 2, 3, 4, 5, 6, 7, 8, 9,
'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3',
'Выход', 'описание', 'фиксированный', 'нефиксировано'
}
local anonToShaped = { 'A1', 'B1', 'C1', 'A2', 'B2', 'C2', 'A3', 'B3', 'C3' }
local shapedToAnon = { A1 = 1, B1 = 2, C1 = 3, A2 = 4, B2 = 5, C2 = 6, A3 = 7, B3 = 8, C3 = 9 }
local data = ''
if args["категория"] then
data = f:callParserFunction( '#dpl:', {
category = args["категория"],
nottitleregexp = args["игнорировать"],
include = '{Крафт}:' .. table.concat( argList, ':' ),
mode = 'userformat',
secseparators = '====',
multisecseparators = '====',
} )
else
-- #dpl может обрабатывать максимум 4 категории сразу, поэтому обрабатываем группами по 4
for i = 1, #ingredients, 4 do
data = data .. f:callParserFunction( '#dpl:', {
category = table.concat( ingredients, ' как ингредиент для крафта|', i, math.min( i + 3, #ingredients ) ) .. ' как ингредиент для крафта',
nottitleregexp = args["игнорировать"],
include = '{Крафт}:' .. table.concat( argList, ':' ),
mode = 'userformat',
secseparators = '====',
multisecseparators = '====',
} )
end
end
-- Закомментируйте следующую строку, если псевдонимы не поддерживаются
local aliases = mw.loadData( 'Модуль:Инвентарный слот/Псевдонимы' )
local function matchPattern( ingredient, ingredientNum )
local matchType = matchTypes
if type( matchType ) == 'table' then
matchType = matchTypes[ingredientNum]
end
local pattern
local escaped = mw.ustring.lower(mw.ustring.gsub(ingredient, '([()%[%]])', '%%%1' ))
if matchType == 'начало' then
pattern = '[;:%]]%s*' .. escaped
elseif matchType == 'конец' then
pattern = escaped .. '%s*[,;%[]'
elseif matchType == 'любое' 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 mw.ustring.find(template, '^%s*|' ) then
local tArgs = {}
local i = 0
-- Разбор аргументов из запроса DPL
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 '',
["Выход"] = tArgs["Выход"]
}
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 _, frameText in ipairs(splitOnUnenclosedSemicolons(v)) do
local frame = slot.getParts( frameText )
local alias = aliases[frame.name]
if alias then
local expandedAlias = slot.expandAlias( frame, alias )
if type(expandedAlias) == 'table' then
-- Псевдоним в новом формате, временно преобразуем его
-- в старый текстовый формат
expandedAlias = slot.stringifyFrames(expandedAlias)
end
local expandedFramePart = mw.ustring.gsub(expandedAlias, '([()%[%]])', '%%%1' )
expandedFramePart = mw.ustring.gsub(expandedAlias, ',?%[%]', '')
expandedFrames[i][frame] = expandedFramePart
table.insert( expandedFrame, expandedAlias )
else
table.insert( expandedFrame, frameText )
end
end
v = table.concat( expandedFrame, ';' )
craftingArgs[i] = v
end
if i ~= 'Выход' then
local delimitedFrames = ';' .. mw.ustring.lower(v) .. ';'
for ingredientNum, ingredient in pairs( ingredients ) do
if mw.ustring.find(delimitedFrames, matchPattern( ingredient, ingredientNum ) ) then
if not mw.ustring.find(v, ';' ) then
hasIngredient = 'static'
elseif not hasIngredient then
hasIngredient = 'animated'
end
argsWithIngredient[i] = true
end
end
end
if not tArgs["группыарг"] 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["описание"] then
showDescription = true
end
if hasIngredient == 'animated' then
if tArgs["группыарг"] then
for _, argGroup in ipairs(splitOnUnenclosedSemicolons(tArgs["группыарг"])) 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 = mw.ustring.gsub(craftingArgs[arg], ';', '' )
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 ipairs(splitOnUnenclosedSemicolons(frames)) do
frameNum = frameNum + 1
if not requiredFrames[frameNum] then
local delimitedFrame = ';' .. frame .. ';'
for ingredientNum, ingredient in pairs( ingredients ) do
if mw.ustring.find(delimitedFrame, matchPattern( ingredient, ingredientNum ) ) then
requiredFrames[frameNum] = true
requiredFramesCount = requiredFramesCount + 1
end
end
end
end
end
end
-- Будут показаны не все фреймы...
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 ipairs(splitOnUnenclosedSemicolons(frames)) do
frameNum = frameNum + 1
if requiredFrames[frameNum] then
table.insert( newFrames, frame )
end
end
newFrames = table.concat( newFrames, ';' )
-- Если весь разобранный псевдоним остался, заново соберём его
if expandedFrames[arg] then
for frame, expandedAlias in pairs( expandedFrames[arg] ) do
--newFrames = 'blah' .. expandedAlias
newFrames = mw.ustring.gsub(newFrames, expandedAlias, frame )
end
end
local tArg = arg
if arg ~= 'Выход' and not tArgs[1] then
tArg = anonToShaped[arg]
end
tArgs[tArg] = newFrames
end
-- Заботу о колонках имени и ингредиентов возложим на модуль Крафт
tArgs["имя"] = nil
tArgs["ингредиенты"] = nil
end
end
end
tArgs["некат"] = '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 '[[Категория:Пустые перечисления использования для крафта]]'
end
templates[1]["глава"] = '1'
templates[1]["показатьимя"] = '1'
if showDescription and args["показатьописание"] ~= '0' or args["показатьописание"] == '1' then
templates[1]["показатьописание"] = '1'
end
if not args["продолжить"] then
templates[#templates]["подвал"] = '1'
end
local crafting = require( 'Модуль:Крафт' )
local out = {}
for i, v in ipairs( templates ) do
table.insert( out, '\n' .. crafting.table( v ) )
end
return table.concat( out, '\n' )
end
return p