Module:Infobox Recipe: Difference between revisions
(checks for a parameter "passive" in the template, and if it is true it displays Passive next to the experience with a tooltip) |
m (different variable names for Full Recipe XP and passive's per-hour recipe XP) |
||
(5 intermediate revisions by 2 users not shown) | |||
Line 8: | Line 8: | ||
local album_xp_data = mw.loadData('Module:Experience/data').album |
local album_xp_data = mw.loadData('Module:Experience/data').album |
||
local lang = mw.language.getContentLanguage() |
local lang = mw.language.getContentLanguage() |
||
local tooltip = require('Module:Tooltip') |
|||
local function formatNum(n) |
local function formatNum(n) |
||
Line 76: | Line 77: | ||
['Recipe JSON'] = mw.text.jsonEncode({ |
['Recipe JSON'] = mw.text.jsonEncode({ |
||
facility = args.facility, |
|||
xp = args.exp and tonumber(args.exp), |
xp = args.exp and tonumber(args.exp), |
||
kp = args.kp and tonumber(args.kp), |
kp = args.kp and tonumber(args.kp), |
||
duration = args.duration, |
duration = args.duration and tonumber(args.duration), |
||
materials = argsMaterials, |
materials = argsMaterials, |
||
profession = args.profession, |
profession = args.profession, |
||
passive = passive, |
|||
level = args.level and tonumber(args.level), |
level = args.level and tonumber(args.level), |
||
-- Make sure to update this when multiple outputs are supported |
-- Make sure to update this when multiple outputs are supported |
||
Line 106: | Line 109: | ||
-- display XP and duration totals for multi-step process |
-- display XP and duration totals for multi-step process |
||
args. |
args.fullXP = tonumber(args.exp) and searchResult.xp and searchResult.xp + tonumber(args.exp) |
||
args.displayDuration = tonumber(args.duration) and searchResult.duration and searchResult.duration + tonumber(args.duration) |
args.displayDuration = tonumber(args.duration) and searchResult.duration and searchResult.duration + tonumber(args.duration) |
||
Line 112: | Line 115: | ||
rawMaterials = argsMaterials |
rawMaterials = argsMaterials |
||
end |
end |
||
--If it is a passive recipe, will want to display the per-hour values for XP and materials used |
|||
args.recipePerHour = args.duration and math.floor(3600/args.duration) |
|||
args.displayXP = (tonumber(args.exp) and args.recipePerHour and tonumber(args.exp) * args.recipePerHour) or '' |
|||
args.displayOutput1qty = (args.output1qty and args.recipePerHour and args.output1qty * args.recipePerHour) or '' |
|||
--Simple query to get the shop buy price for the provided material, if no buy price is available returns 0 |
--Simple query to get the shop buy price for the provided material, if no buy price is available returns 0 |
||
Line 144: | Line 152: | ||
local materialBuyPrice = getBuyPrice(item) * (item.quantity or 1) |
local materialBuyPrice = getBuyPrice(item) * (item.quantity or 1) |
||
rawMaterialCost = rawMaterialCost + materialBuyPrice |
rawMaterialCost = rawMaterialCost + materialBuyPrice |
||
local displayQuantity = item.quantity or 1 |
|||
if passive then |
|||
displayQuantity = displayQuantity and args.recipePerHour and displayQuantity * args.recipePerHour |
|||
end |
|||
return mw.html.create('tr') |
return mw.html.create('tr') |
||
:tag('td') |
:tag('td') |
||
Line 156: | Line 168: | ||
:css{ ['text-align'] = 'right' } |
:css{ ['text-align'] = 'right' } |
||
:wikitext(item.quantity or 1) |
:wikitext(item.quantity or 1) |
||
:IF(passive) |
|||
:wikitext('<br>( ' .. displayQuantity .. ' per hour)' ) |
|||
:END() |
|||
:done() |
:done() |
||
:node(currency_cell(materialBuyPrice)) |
:node(currency_cell(materialBuyPrice)) |
||
Line 214: | Line 229: | ||
:attr{ colspan = '2' } |
:attr{ colspan = '2' } |
||
:IF(passive) |
:IF(passive) |
||
:wikitext('[[File:Passive small icon.png|20x20px|link=Passive Activity]] [[Passive Activity|Passive]] [[Experience]]') |
:wikitext('[[File:Passive small icon.png|20x20px|link=Passive Activity]] [[Passive Activity|Passive]] [[Experience]] ') |
||
:node(tooltip._span{ 'passive' }) |
|||
: |
:node(tooltip._div{ name = 'passive', content = 'Passive activities give reduced experience when a players level is high enough to perform a new passive activity for that profession. The number shown here is the full experience.' }) |
||
:ELSE() |
:ELSE() |
||
:wikitext('[[Experience]]') |
:wikitext('[[Experience]]') |
||
Line 226: | Line 242: | ||
:IF(showFullRecipe) |
:IF(showFullRecipe) |
||
:wikitext(' (') |
:wikitext(' (') |
||
:wikitext(hc(args. |
:wikitext(hc(args.fullXP) and (formatNum(tonumber(args.fullXP))) or ("'''?'''")) |
||
:wikitext(' total)') |
:wikitext(' total)') |
||
:END() |
|||
:IF(passive) |
|||
:wikitext(' (') |
|||
:wikitext(hc(args.displayXP) and (formatNum(tonumber(args.displayXP))) or ("'''?'''")) |
|||
:wikitext(' per hour)') |
|||
:END() |
:END() |
||
:done() |
:done() |
||
Line 261: | Line 282: | ||
:tag('th') |
:tag('th') |
||
:attr{ colspan = '5' } |
:attr{ colspan = '5' } |
||
:wikitext('[[Album|Album XP]]') |
:wikitext('[[Album|Album XP]] ') |
||
:node(tooltip._span{ 'album' }) |
|||
:node(tooltip._div{ name = 'album', content = 'Album XP is a bonus awarded once for the first time the activity is performed.' }) |
|||
:done() |
:done() |
||
:done() |
:done() |
||
Line 379: | Line 402: | ||
:css{ ['text-align'] = 'right' } |
:css{ ['text-align'] = 'right' } |
||
:wikitext(args.output1qty or 1) |
:wikitext(args.output1qty or 1) |
||
:IF(passive) |
|||
:wikitext('<br>( ' .. args.displayOutput1qty .. ' per hour)' ) |
|||
:END() |
|||
:done() |
:done() |
||
:node(currency_cell(output1TotalValue)) |
:node(currency_cell(output1TotalValue)) |
Latest revision as of 19:28, 28 December 2024
Module documentation
This documentation is transcluded from Module:Infobox Recipe/doc. [edit] [history] [purge]
Module:Infobox Recipe's function _main is invoked by Template:Infobox Recipe.
Module:Infobox Recipe requires
.Module:Infobox Recipe loads data from Module:Experience/data.
This module invoked using the command
{{#invoke:Infobox Recipe|_main}}
It provides this functionality to Template:Infobox Recipe
require('strict')
require('Module:Mw.html extension')
local currency = require('Module:Currency')
local hc = require('Module:Param Parse').has_content
local yn = require('Module:Yesno')
local search = require('Module:RecipeTreeSearch')
local editButton = require('Module:Edit button')
local album_xp_data = mw.loadData('Module:Experience/data').album
local lang = mw.language.getContentLanguage()
local tooltip = require('Module:Tooltip')
local function formatNum(n)
if n == nil then
return ''
end
return lang:formatNum(n)
end
local function currency_cell(amount)
return currency._cell(amount, { html = 'yes' })
end
local p = {}
function p._main(frame)
local args = frame:getParent().args
--If set to true, will check if any of the items passed as a rawmaterialparam are actually intermediate materials. Will then change the display order of the infobox.
local showFullRecipe = yn(args.showFull or 'no', false)
--If set to true, will check hide the album xp section as the item does not give album xp.
local hideAlbum = yn(args.hideAlbum or 'no', false)
--Checks if the recipe has been flagged as passive, defaults to no.
local passive = yn(args.passive or 'no', false)
--Get each of the rawmatX parameters from params and store their values in a new table
local argsMaterials = p._extractRawMaterials(args)
--empty tables to hold materials
local rawMaterials = {}
local intermediateMaterials = {}
--counter for total price of raw materials
local rawMaterialCost = 0
--get the value for the output product
local output1Value = 0
if args.output1 then
output1Value = mw.smw.ask('[[:+]][[' .. args.output1 .. ']]|?Value|limit=1') or 0
end
--Calculate total value of output material(s)
local output1TotalValue = 0
if type(output1Value) == "table" then
if output1Value[1]['Value'] ~= nil then
output1TotalValue = output1Value[1]['Value'] * (tonumber(args.output1qty) or 1)
else
output1TotalValue = 0
end
end
-- if the recipe is part of a quest
args.quest = args.quest or false
--Set SMW properties early, so latter parts can potentially use it.
local smw_properties = {
['Uses item'] = {},
-- these are for when a recipe is called by a subsequent recipe that uses showFull
['Uses facility'] = args.facility,
-- these are for generating tables of profession xp rates and profits
['Activity XP'] = args.exp,
['Activity album XP'] = album_xp_data[tonumber(args.level)],
['Activity KP'] = args.kp,
['Activity duration'] = args.duration,
['Activity level'] = args.level and tonumber(args.level),
['Recipe JSON'] = mw.text.jsonEncode({
facility = args.facility,
xp = args.exp and tonumber(args.exp),
kp = args.kp and tonumber(args.kp),
duration = args.duration and tonumber(args.duration),
materials = argsMaterials,
profession = args.profession,
passive = passive,
level = args.level and tonumber(args.level),
-- Make sure to update this when multiple outputs are supported
output = {
{ name = args.output1, quantity = tonumber(args.output1qty) or 1 },
}
}),
-- Make sure to update this when multiple outputs are supported to be a list of all outputs
['Recipe output'] = { args.output1 }
}
for _, material in ipairs(argsMaterials) do
table.insert(smw_properties['Uses item'], material.name)
end
mw.smw.set(smw_properties)
--Check if any of the raw mats provided are intermediate products, if they are, return their own raw materials
if showFullRecipe then
-- Use the RecipeTreeSearch module to get all the rawMaterials needed to make output1
local searchResult = search.treeSearch(argsMaterials)
rawMaterials = searchResult.materials
intermediateMaterials = p._reverseTable(searchResult.intermediateMaterials)
-- display XP and duration totals for multi-step process
args.fullXP = tonumber(args.exp) and searchResult.xp and searchResult.xp + tonumber(args.exp)
args.displayDuration = tonumber(args.duration) and searchResult.duration and searchResult.duration + tonumber(args.duration)
else
rawMaterials = argsMaterials
end
--If it is a passive recipe, will want to display the per-hour values for XP and materials used
args.recipePerHour = args.duration and math.floor(3600/args.duration)
args.displayXP = (tonumber(args.exp) and args.recipePerHour and tonumber(args.exp) * args.recipePerHour) or ''
args.displayOutput1qty = (args.output1qty and args.recipePerHour and args.output1qty * args.recipePerHour) or ''
--Simple query to get the shop buy price for the provided material, if no buy price is available returns 0
local function getBuyPrice(material)
local queryResult = mw.smw.ask('[[:+]][[Sold item::' .. material['name'] .. ']]|?Shop buy price|sort=Shop buy price|order=asc|limit=1') or 0
if type(queryResult) == "table" and queryResult[1]['Shop buy price'] then
return tonumber(queryResult[1]['Shop buy price']) or 0
end
return 0
end
--If one of the raw materials provided as a param has been identified as an intermediate material then get the facility it is created at to display in the intermediate Ingredient row
local function getFacility(material)
local result = mw.smw.ask('[[:+]][[' .. material .. ']]|?Uses facility|limit=1') or 'unknown'
local pageName = ''
if result and result[1] and result[1]["Uses facility"] then
local usesFac = result[1]["Uses facility"]
pageName = usesFac:gsub("%[%[", ""):gsub("%]%]", ""):gsub("|.*", ""):gsub("^:", "")
end
return pageName
end
local album_xp = album_xp_data[tonumber(args.level)]
if (album_xp) then
album_xp = formatNum(album_xp)..' xp'
end
--Creates a row suitable for the raw materials section of the infobox.
local function createRawMaterialRow(item)
local materialBuyPrice = getBuyPrice(item) * (item.quantity or 1)
rawMaterialCost = rawMaterialCost + materialBuyPrice
local displayQuantity = item.quantity or 1
if passive then
displayQuantity = displayQuantity and args.recipePerHour and displayQuantity * args.recipePerHour
end
return mw.html.create('tr')
:tag('td')
:css{ ['border-right'] = 'none' }
:wikitext('[[File:' .. item.name .. '.png|30px|link=' .. item.name .. ']]')
:done()
:tag('td')
:css{ ['border-left'] = 'none' }
:wikitext('[[' .. item.name .. ']]')
:done()
:tag('td')
:css{ ['text-align'] = 'right' }
:wikitext(item.quantity or 1)
:IF(passive)
:wikitext('<br>( ' .. displayQuantity .. ' per hour)' )
:END()
:done()
:node(currency_cell(materialBuyPrice))
:done()
end
--Creates a row suitable for the intermediate materials section of the infobox.
local function createIntermediateMaterialRow(item)
local facility = getFacility(item.name)
return mw.html.create('tr')
:tag('td')
:css{ ['border-right'] = 'none' }
:wikitext('[[File:' .. item.name .. '.png|30px|link=' .. item.name .. ']]')
:done()
:tag('td')
:css{ ['border-left'] = 'none' }
:wikitext('[[' .. item.name .. ']]')
:done()
:tag('td')
:css{ ['text-align'] = 'right' }
:wikitext(item.quantity or 1)
:done()
:tag('td')
:attr{ colspan = '10' }
:css{ ['text-align'] = 'center' }
:wikitext('[[File:' .. facility .. '.png|30px|link=' .. facility .. ']] [[' .. facility .. ']]')
:done()
:done()
end
-- Recipe Table Head
local out = mw.html.create('table')
:addClass('wikitable')
:tag('tr')
:tag('th')
:attr{ colspan = '13' }
:wikitext('Requirements')
:done()
:done()
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Facility')
:done()
:tag('td')
:attr{ colspan = '11' }
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.facility) and ('[[File:%s.png|link=%s|30px]] [[%s]]'):format(args.facility, args.facility, args.facility) or editButton("'''?''' (edit)").. '[[Category:Needs facility recipe]]')
:done()
:done()
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:IF(passive)
:wikitext('[[File:Passive small icon.png|20x20px|link=Passive Activity]] [[Passive Activity|Passive]] [[Experience]] ')
:node(tooltip._span{ 'passive' })
:node(tooltip._div{ name = 'passive', content = 'Passive activities give reduced experience when a players level is high enough to perform a new passive activity for that profession. The number shown here is the full experience.' })
:ELSE()
:wikitext('[[Experience]]')
:END()
:done()
:tag('td')
:attr{ colspan = '11' }
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.exp) and (formatNum(tonumber(args.exp))) or editButton("'''?''' (edit)").. '[[Category:Needs experience recipe]]')
:IF(showFullRecipe)
:wikitext(' (')
:wikitext(hc(args.fullXP) and (formatNum(tonumber(args.fullXP))) or ("'''?'''"))
:wikitext(' total)')
:END()
:IF(passive)
:wikitext(' (')
:wikitext(hc(args.displayXP) and (formatNum(tonumber(args.displayXP))) or ("'''?'''"))
:wikitext(' per hour)')
:END()
:done()
:done()
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Duration')
:done()
:tag('td')
:attr{ colspan = '11' }
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.duration) and ('%s seconds'):format(args.duration) or editButton("'''?''' (edit)").. '[[Category:Needs duration recipe]]')
:IF(showFullRecipe)
:wikitext(' (')
:wikitext(hc(args.displayDuration) and (args.displayDuration) or ("'''?'''"))
:wikitext(' total)')
:END()
:done()
:done()
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Profession')
:done()
:tag('th')
:wikitext('Level')
:done()
:tag('th')
:attr{ colspan = '5' }
:wikitext('[[Knowledge|KP]]')
:done()
:tag('th')
:attr{ colspan = '5' }
:wikitext('[[Album|Album XP]] ')
:node(tooltip._span{ 'album' })
:node(tooltip._div{ name = 'album', content = 'Album XP is a bonus awarded once for the first time the activity is performed.' })
:done()
:done()
:tag('tr')
:tag('td')
:attr{ colspan = '2' }
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.profession) and ('[[' .. args.profession .. ']]') or editButton("'''?''' (edit)").. '[[Category:Needs profession recipe]]')
:done()
:tag('td')
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.level) and (args.level) or editButton("'''?''' (edit)").. '[[Category:Needs level recipe]]')
:done()
:tag('td')
:attr{ colspan = '5' }
:css{ ['text-align'] = 'center' }
:wikitext(hc(args.kp) and ('%s%%'):format(args.kp) or editButton("'''?''' (edit)").. '[[Category:Needs knowledge recipe]]')
:done()
:tag('td')
:attr{ colspan = '5' }
:css{ ['text-align'] = 'center' }
:IF(hideAlbum)
:wikitext('N/A')
:ELSE()
:wikitext(album_xp or 'Unknown')
:END()
:done()
:done()
-- Add raw materials
-- Headers
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Raw Ingredient')
:done()
:tag('th')
:wikitext('Quantity')
:done()
:tag('th')
:attr{ colspan = '10' }
:wikitext('Cost')
:done()
:done()
-- Values
for _, material in ipairs(rawMaterials) do
out:node(createRawMaterialRow(material))
end
-- Add total raw cost
out
:tag('tr')
:tag('th')
:attr{ colspan = '3' }
:wikitext('Total Raw cost')
:done()
:node(currency_cell(rawMaterialCost))
:done()
-- Add Intermediate steps if required
-- Headers
if next(intermediateMaterials) ~= nil then
-- Headers
out
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Intermediate Ingredient')
:done()
:tag('th')
:wikitext('Quantity')
:done()
:tag('th')
:attr{ colspan = '10' }
:wikitext('Faciltity')
:done()
:done()
-- Values
for _, material in ipairs(intermediateMaterials) do
mw.logObject(material)
out:node(createIntermediateMaterialRow(material))
end
end
-- Add output data
-- Headers
out
:tag('tr')
:tag('th')
:attr{ colspan = '2' }
:wikitext('Output')
:done()
:tag('th')
:wikitext('Quantity')
:done()
:tag('th')
:attr{ colspan = '10' }
:wikitext('Value')
:done()
:done()
:IF(args.output1)
-- Values
:tag('tr')
:tag('td')
:css{ ['border-right'] = 'none' }
:wikitext('[[File:' .. args.output1 .. '.png|30px|link=' .. args.output1 .. ']]' or 'Unknown')
:done()
:tag('td')
:css{ ['border-left'] = 'none' }
:wikitext('[[' .. args.output1 .. ']]' or 'Unknown')
:done()
:tag('td')
:css{ ['text-align'] = 'right' }
:wikitext(args.output1qty or 1)
:IF(passive)
:wikitext('<br>( ' .. args.displayOutput1qty .. ' per hour)' )
:END()
:done()
:node(currency_cell(output1TotalValue))
:done()
:END()
-- Add profit data
:tag('tr')
:addClass('currency')
:tag('th')
:attr{ colspan = '3' }
:wikitext('Profit')
:done()
:node(currency_cell(output1TotalValue - rawMaterialCost))
:done()
return out
end
function p._extractRawMaterials(args)
local rawMaterials = {}
for i = 1, 9 do
local materialKey = "rawmat" .. i
local quantityKey = "rawmat" .. i .. "qty"
local materialValue = args[materialKey]
if materialValue and materialValue ~= "" then
local quantityValue = tonumber(args[quantityKey]) or 1
table.insert(rawMaterials, { name = materialValue, quantity = quantityValue })
end
end
return rawMaterials
end
function p._reverseTable(t)
local reversed = {}
for i = #t, 1, -1 do
table.insert(reversed, t[i])
end
return reversed
end
return p