Module:Ingredient Utilization
Documentation for this module may be created at Module:Ingredient Utilization/doc
local p = {}
local utils = require('Module:Utils')
local items = require('Module:Item')
local inline = require('Module:CraftInline')
local i18n = mw.loadData('Module:Ingredient Utilization/i18n')
local categories = mw.loadData('Module:Item/Categories')
--★Elin:アイテム名 num skin+Numの場合もある
local function checkFullNameAndMatchPageName(fullName, name)
local fullNameName = string.gsub( fullName, 'Elin:%s*', '' )
if fullNameName ~= name then
local pattern1 = '^(.+) ([0-9]+)$'
local match1_1, match1_2 = mw.ustring.match(fullNameName, pattern1)
--mw.log('match1_1: ' , tostring(match1_1))
--mw.log('match1_2: ' , tostring(match1_2))
return match1_1, match1_2, fullNameName
end
return nil, nil, fullNameName
end
--valueをname,mat,skin,varietyに分離
local function getResultItem(value)
local name = value
local num
local mat
local skin
local var
local ele
if not name then
return
end
if string.find(name, '/') then
name, num = name:match('([^/]+)/([^/]+)')
end
if string.find(name, '@') then
name, mat = name:match('([^@]+)@([^@]+)')
end
if string.find(name, ':') then
name, skin = name:match('([^:]+):([^:]+)')
end
if string.find(name, '_') then
name, var = name:match('([^_]+)_([^_]+)')
end
if string.find(name, '%+') then
name, element = name:match("([^%+]+)%+([^%+]+)")
end
return name, num, mat, skin, var, ele
end
function p.ask(frame)
local lang = utils.nilIfEmpty(frame.args['lang']) or 'JA'
if not mw.smw then
error(tostring(i18n[lang]['error_mwsmw']))
end
local currentPage = mw.title.getCurrentTitle()
local pageName = currentPage.text
local fullPageName = currentPage.fullText
local parentArgs = frame:getParent().args
local pageCut = parentArgs['pageCut'] or true
local icon = utils.nilIfEmpty(parentArgs['icon'])
local highlight = parentArgs['highlight'] or 'true'
local args = {}
args[1] = pageName
args[2] = pageName..'+'
local highlightParent = {}
if parentArgs then
local nextIndex = 3
for key, value in pairs(parentArgs) do
if type(key) == 'number' then
args[nextIndex] = value
nextIndex = nextIndex + 1
if highlight == 'true' then
table.insert(highlightParent, value)
end
else
args[key] = value
end
end
if highlight == 'true' then
table.insert(highlightParent, pageName)
--mw.log('highlightParent: ',tostring(highlightParent))
end
end
if args == nil then
error(tostring(i18n[lang]['error_arg']))
end
local allResults = {}
local mode = frame.args['mode'] or utils.nilIfEmpty(args['mode']) or 'table'
if mode ~= 'table' and mode ~= 'list' and mode ~= 'item' and mode ~= 'craftstation' then
error(tostring(i18n[lang]['error_mode']))
end
for key, value in pairs(frame.args) do
if type(key) == 'number' then
args[key] = value
end
end
--加工設備除外リスト
local ExcludeProcessor
local ResultProcessorList = {}
if args['case'] and type(args['case']) == 'string' then
ExcludeProcessor = string.find(args['case'],'noProcessor')
if ExcludeProcessor then
local ProcessorList = {
'klin',
'jewelybench',
'factory_sculpture',
'dyemaker',
'factory_barrel',
'beehive',
'shelf_aging',
'brewery',
'dry_brick',
'dry_rack',
'sawmill',
'spinner',
'grindstone',
'stonecutter',
'smelter',
'millstone',
'millstone_wood',
'incubator',
'rationmaker',
'453'
}
if lang == 'JA' then
local dataAliases = mw.loadData('Module:Item/JaAliases')
for _, processor in ipairs(ProcessorList) do
for jaAlias, idAlias in pairs(dataAliases) do
if idAlias == processor then
table.insert(ResultProcessorList, jaAlias)
break
end
end
end
elseif lang == 'EN' then
local dataAliases = mw.loadData('Module:Item/IDAliases')
for _, processor in ipairs(ProcessorList) do
for enAlias, idAlias in pairs(dataAliases) do
if idAlias == processor then
table.insert(ResultProcessorList, enAlias)
break
end
end
end
else
ResultProcessorList = ProcessorList
end
end
end
--除外用アイテムのテーブル作成
local excludeArg = utils.nilIfEmpty(args[i18n[lang]['ExcludedItems']])
local excludedItemsList = {}
--呼び出し元テンプレートに設定された除外アイテムの追加
if excludeArg then
local splitResult = {}
splitResult = mw.text.split(excludeArg, ',')
if type(splitResult) ~= 'table' then
splitResult = { splitResult }
end
for _, item in ipairs(splitResult) do
table.insert(excludedItemsList, mw.text.trim(item))
end
end
--呼び出し元のフルページ名に設定された除外アイテムの追加
local query = string.format('[[%s]]|?%s|?%s', fullPageName, 'CraftingExcludedItems', 'Name')
local result = mw.smw.ask(query)
local PropertyName
local splitExcludedItems
if result then
PropertyName = result[1]['Name']
splitExcludedItems = result[1]['CraftingExcludedItems'] and mw.text.split(result[1]['CraftingExcludedItems'], '%s*,%s*') or result[1]['CraftingExcludedItems']
end
if splitExcludedItems then
if type(splitExcludedItems) ~= 'table' then
splitExcludedItems = { splitExcludedItems }
end
for _, value in ipairs(splitExcludedItems) do
table.insert(excludedItemsList, value)
end
end
-- excludedItemsList内の重複削除
if #excludedItemsList > 0 then
local seen = {}
local uniqueExcludeItems = {}
for _, item in ipairs(excludedItemsList) do
if not seen[item] then
seen[item] = true
table.insert(uniqueExcludeItems, item)
end
end
excludedItemsList = uniqueExcludeItems
end
mw.log('除外アイテムリスト')
mw.logObject(excludedItemsList)
for i = 1, #args do
if args[i] then
mw.log('label'..i..':'..args[i])
local query
if mode == 'craftstation' then
query = '[[Category:Elin '..i18n[lang]['ITEM']..']] [[Category:Elin '..args[i]..']]'
else
if string.find(args[i], '%+') then
query = '[[Category:Elin '..i18n[lang]['ITEM']..']] [[IngredientAll::'..args[i]..'*]] OR [[IngredientAll::~*,'..args[i]..'*]] OR [[IngredientAll::~*'..args[i]..'*]]'
else
query = '[[Category:Elin '..i18n[lang]['ITEM']..']] [[IngredientAll::'..args[i]..']] OR [[IngredientAll::~*,'..args[i]..'*]] OR [[IngredientAll::~*'..args[i]..',*]]'
end
end
local resultN = mw.smw.ask{
query,
'?ID',
'?Name',
'?Full Name',
'?ItemLv',
'?Type',
'?CraftingStation',
'?Ingredient',
'?IngredientNum',
'?IngredientExtra',
'?CraftingStation2',
'?Ingredient2',
'?IngredientNum2',
'?IngredientExtra2',
'?CraftingStation3',
'?Ingredient3',
'?IngredientNum3',
'?IngredientExtra3',
'?CraftingResult',
'?CraftingResult2',
'?CraftingResult3',
'?ElementNote',
limit = 99,
mainlabel = '-'
} or {}
--excludedItemsListの除外アイテムをresultNから省いて新しくテーブルを作成する
for _, row in pairs(resultN) do
local shouldInsert = true
if row['Full Name'] == fullPageName and pageCut == true then
shouldInsert = false
elseif #excludedItemsList > 0 and table.indexOf(excludedItemsList, tostring((row['Full Name'] or ''):gsub('Elin:%s*', ''))) then
shouldInsert = false
elseif ExcludeProcessor then
local checkStations = {}
local stationStrings = {row.CraftingStation, row.CraftingStation2, row.CraftingStation3}
for _, s in ipairs(stationStrings) do
if s then
local splitStations = mw.text.split(s, ',')
for _, st in ipairs(splitStations) do
table.insert(checkStations, mw.text.trim(st))
end
end
end
if checkStations then
for _, station in ipairs(checkStations) do
if station and table.indexOf(ResultProcessorList, mw.text.trim(station)) then
shouldInsert = false
break
end
end
end
end
--allResults挿入確定
if shouldInsert then
--sortValの追加
if row.Type then
for catKey, catValue in pairs(categories) do
if lang == 'JA' and row.Type == catValue.name_JP or
lang == 'EN' and row.Type == catValue.name then
row.sortVal = catValue.sortVal
break
end
end
end
if not row.sortVal then
row.sortVal = 0
end
table.insert(allResults, row)
end
end
end
end
-- allResults 重複削除
local uniqueResults = {}
local names = {}
for _, row in pairs(allResults) do
if row['Full Name'] then
local itemName = tostring(row['Full Name'])
if not names[itemName] then
table.insert(uniqueResults, row)
names[itemName] = true
end
end
end
if #uniqueResults > 0 then
--modeの強制変更 テーブル型だと実時間が長くなりやすい。アイテムページが増えすぎた場合に行う
--if #uniqueResults > 30 then
-- mode = 'list'
--end
--プロパティとカテゴリ追加用
local addcategory = ''
if currentPage.nsText == 'Elin' then
utils.setPropertyData('Use',i18n[lang]['use'])
addcategory = i18n[lang]['category']
end
--ソート
local function sortByTypeAndItemLv(a, b)
if a.sortVal ~= b.sortVal then
return a.sortVal < b.sortVal
else
local itemLvA = tonumber(a.ItemLv) or 0
local itemLvB = tonumber(b.ItemLv) or 0
return itemLvA < itemLvB
end
end
local function sortByItemLv(a, b)
local itemLvA = tonumber(a.ItemLv) or 0
local itemLvB = tonumber(b.ItemLv) or 0
return itemLvA < itemLvB
end
if mode == 'craftstation' then
table.sort(uniqueResults, sortByItemLv)
else
table.sort(uniqueResults, sortByTypeAndItemLv)
end
if mode == 'list' then
--=====リストで表示=====
local listResult = ''
local stationItems = {}
for _, row in pairs(uniqueResults) do
local name = row.Name or ''
local fullName = row['Full Name'] or ''
local craftingStation = row.CraftingStation or ''
local stations = string.find(craftingStation, ',') and mw.text.split(craftingStation, ',') or {mw.text.trim(craftingStation)}
for _, station in ipairs(stations) do
local trimmedStation = mw.text.trim(station)
if stationItems[trimmedStation] then
table.insert(stationItems[trimmedStation], '[['..fullName..'|'..name..']]')
else
stationItems[trimmedStation] = { '[['..fullName..'|'..name..']]' }
end
end
end
for station, items in pairs(stationItems) do
local separator = i18n[lang]['list_separator']
local formatString = i18n[lang]['list_format']
local itemString = table.concat(items, separator)
if lang == 'EN' and #items > 1 then
local lastItem = table.remove(items)
itemString = table.concat(items, separator)..i18n[lang]['list_and']..lastItem
end
listResult = listResult..'*'..string.format(formatString, station, itemString)..'<br>\n'
end
return listResult, addcategory
elseif mode == 'table' or mode == 'craftstation' then
--=====テーブルで表示=====
local html = mw.html.create('div')
if #uniqueResults > 10 then
html:wikitext(frame:expandTemplate{ title = 'Collapse top', args = { lang = lang, expanded = 1, width = 'auto' } })
end
local table = html:tag('table'):addClass('wikitable sortable')
local headerRow = table:tag('tr')
headerRow:tag('th'):wikitext(i18n[lang]['th_Craft'])
headerRow:tag('th'):wikitext(i18n[lang]['th_Ingredient'])
if mode == 'table' then headerRow:tag('th'):wikitext(i18n[lang]['th_CraftingStation']) end
headerRow:tag('th'):wikitext(i18n[lang]['th_Type'])
headerRow:tag('th'):wikitext(i18n[lang]['th_Lv'])
for _, row in pairs(uniqueResults) do
local Name = row.Name or ''
local fullName = row['Full Name'] or ''
local ingredient = row.Ingredient or ''
local ingredientNum = row.IngredientNum or ''
local ingredientExtra = row.IngredientExtra or ''
local ingredient2 = row.Ingredient2 or ''
local ingredientNum2 = row.IngredientNum2 or ''
local ingredientExtra2 = row.IngredientExtra2 or ''
local ingredient3 = row.Ingredient3 or ''
local ingredientNum3 = row.IngredientNum3 or ''
local ingredientExtra3 = row.IngredientExtra3 or ''
local craftingStation = row.CraftingStation or ''
local craftingStation2 = row.CraftingStation2 or ''
local craftingStation3 = row.CraftingStation3 or ''
local craftingResult = row.CraftingResult or ''
local craftingResult2 = row.CraftingResult2 or ''
local craftingResult3 = row.CraftingResult3 or ''
local ElementNote = row.ElementNote or ''
local itemType = row.Type or ''
local itemLv = row.ItemLv or ''
local setItem, setItems
local itemName, itemNum, itemMat, itemSkin, itemVar, itemEle
local fullNameName
--クラフト結果
if mode == 'craftstation' then
if craftingStation == pageName then
setItem = craftingResult
elseif craftingStation2 == pageName then
setItem = craftingResult2
elseif craftingStation3 == pageName then
setItem = craftingResult3
end
else
--クラフト結果の中に対象アイテム名が含まれている場合にクラフト結果を渡す
if utils.nilCheck(craftingResult) and string.find(craftingResult, Name) then
setItem = craftingResult
elseif utils.nilCheck(craftingResult2) and string.find(craftingResult, Name) then
setItem = craftingResult2
elseif utils.nilCheck(craftingResult3) and string.find(craftingResult, Name) then
setItem = craftingResult3
end
end
if utils.nilCheck(setItem) then
if string.find(setItem, ',') then
setItems = mw.text.split(setItem, '%s*,%s*') or {}
for _, item in ipairs(setItems) do
local parts = mw.text.split(item, '/')
if parts[1] == Name then
setItem = item
break
end
end
end
itemName, itemNum, itemMat, itemSkin, itemVar, itemEle = getResultItem(setItem)
else
--craftingResultが設定されていなければ、ページ名とアイテム名を比較して分離代入
--例えば"牛乳 2"と"牛乳"、"繊維 (雑貨)"と"繊維"、"障子 skin2"と"障子"
--★いずれスキンのページが出た場合はパラメーターskinを入れる。いまはvarietyだけ
itemName, itemVar, fullNameName = checkFullNameAndMatchPageName(fullName, Name)
end
local itemTemplate = items.generateItem({
lang = lang,
name = itemName or fullNameName or Name,
num = itemNum,
itemMat = itemMat,
skin = itemSkin,
variety = itemVar,
element = itemEle,
link = fullName,
icon = icon
})
--材料結果
local stringLength = string.len(ingredient..ingredient2..ingredient3)
local craftTemplate
if row.ID == 'cheese' or row.ID == 'jerky' or row.ID == '48' then
local match1_1, match1_2, fullNameName = checkFullNameAndMatchPageName(pageName, PropertyName)
craftTemplate = '<span class="item-highlight">'..items.generateItem({ lang = lang, name = match1_1 or fullNameName, variety = match1_2, link = fullPageName, icon = icon })..'</span>'..i18n[lang]['andMore']
elseif row.ID == 'fish_slice' then
craftTemplate = '<span class="item-highlight">'..items.generateItem({ lang = lang, name = pageName, link = fullPageName, icon = icon })..'</span>'
else
local inlineData = {
lang = lang,
mode = 'inlinehr',
icon = icon,
highlight = true,
highlightParent = highlightParent,
ElementNote = ElementNote,
['1-2'] = ingredient,
['1-3'] = ingredientNum,
['1-4'] = ingredientExtra,
['2-2'] = ingredient2,
['2-3'] = ingredientNum2,
['2-4'] = ingredientExtra2,
['3-2'] = ingredient3,
['3-3'] = ingredientNum3,
['3-4'] = ingredientExtra3
}
if mode == 'craftstation' then
local foundPrefix = nil
if craftingStation == pageName then
foundPrefix = '1-'
elseif craftingStation2 == pageName then
foundPrefix = '2-'
elseif craftingStation3 == pageName then
foundPrefix = '3-'
end
if foundPrefix then
inlineData['1-2'] = inlineData[foundPrefix .. '2']
inlineData['1-3'] = inlineData[foundPrefix .. '3']
inlineData['1-4'] = inlineData[foundPrefix .. '4']
inlineData['2-2'] = nil; inlineData['2-3'] = nil; inlineData['2-4'] = nil;
inlineData['3-2'] = nil; inlineData['3-3'] = nil; inlineData['3-4'] = nil;
end
end
craftTemplate = inline.generatecraftInline(inlineData)
end
--設備結果
local inlineData = {
lang = lang,
mode = 'inlinehr',
icon = icon,
highlight = true,
highlightParent = highlightParent,
['1-1'] = craftingStation,
['2-1'] = craftingStation2,
['3-1'] = craftingStation3
}
if mode == 'craftstation' then
local foundPrefix = nil
if craftingStation == pageName then
foundPrefix = '1-'
elseif craftingStation2 == pageName then
foundPrefix = '2-'
elseif craftingStation3 == pageName then
foundPrefix = '3-'
end
if foundPrefix then
inlineData['1-1'] = inlineData[foundPrefix .. '1']
inlineData['2-1'] = nil; inlineData['3-1'] = nil
end
end
local stationTemplate = inline.generatecraftInline(inlineData)
local itemTypeString
if itemType == 'アイテム' or itemType == '魚' or itemType == 'きのこ' then
itemTypeString = '[[:Category:Elin '..itemType..' (分類)|'..itemType..']]'
else
itemTypeString = '[[:Category:Elin '..itemType..'|'..itemType..']]'
end
local dataRow = table:tag('tr')
dataRow:tag('td'):wikitext(itemTemplate)
dataRow:tag('td'):wikitext(craftTemplate)
if mode == 'table' then dataRow:tag('td'):wikitext(stationTemplate) end
dataRow:tag('td'):attr('data-sort-value', row.sortVal):wikitext(itemTypeString)
dataRow:tag('td'):wikitext(itemLv)
end
if #uniqueResults > 10 then
html:wikitext(frame:expandTemplate{ title = 'Collapse bottom' })
end
return tostring(html), addcategory
elseif mode == 'item' then
--=====アイテムで表示=====
local maxNameLength = 0
local itemTemplates = {}
for _, row in pairs(uniqueResults) do
local name = row.Name or ''
local fullName = row['Full Name'] or ''
local nameLength = mw.ustring.len(name)
if nameLength > maxNameLength then maxNameLength = nameLength end
local match1_1, match1_2, fullNameName = checkFullNameAndMatchPageName(fullName, name)
table.insert(itemTemplates, items.generateItem({ lang = lang, name = match1_1 or name, variety = match1_2, link = fullName, icon = icon }))
end
local columnWidth = (maxNameLength + 1)..'em'
local itemListArgs = { style = 'column-width:'..columnWidth..';' }
for i, template in ipairs(itemTemplates) do itemListArgs[i] = template end
local itemList = frame:expandTemplate{title = 'Itemlist', args = itemListArgs}
return itemList, addcategory
end
else
return i18n[lang]['error_NoResult']
end
end
function table.indexOf(tab, val)
for i, v in ipairs(tab) do
if v == val then return i end
end
return nil
end
return p