Module:Recipe: Difference between revisions
Jump to navigation
Jump to search
Content added Content deleted
No edit summary |
No edit summary |
||
Line 224: | Line 224: | ||
:tag('td'):attr('colspan', 2):wikitext(skillpic(v.name, nil, true)):done() |
:tag('td'):attr('colspan', 2):wikitext(skillpic(v.name, nil, true)):done() |
||
:tag('td'):wikitext(levelText):done() |
:tag('td'):wikitext(levelText):done() |
||
:tag('td'):wikitext((tonumber(xp) ~= nil and commas._add(xp) or xp) .. citeText):done() |
:tag('td'):wikitext((tonumber(xp) ~= nil and commas._add(xp) or xp) .. " " .. citeText):done() |
||
table.insert(requirements, requirement) |
table.insert(requirements, requirement) |
Revision as of 17:18, 9 November 2024
Module documentation
This documentation is transcluded from Template:No documentation/doc. [edit] [history] [purge]
This module does not have any documentation. Please consider adding documentation at Module:Recipe/doc. [edit]
Module:Recipe's function main is invoked by Template:Recipe.
Module:Recipe requires
.--<nowiki>
local p = {}
-- convert some used globals to locals to improve performance
local math = math
local string = string
local table = table
local mw = mw
local expr = mw.ext.ParserFunctions.expr
local coins = require('Module:Coins')._amount
local yesno = require('Module:Yesno')
local params = require('Module:Paramtest')
local commas = require('Module:Addcommas')
local geprice = require('Module:Exchange')._price
local skillpic = require('Module:SCP')._main
local editbutton = require('Module:Edit button')
local onmain = require('Module:Mainonly').on_main
local currencies = require('Module:Currencies')._amount
local edit = editbutton('? (edit)')
-- Tools that need special handling
local toolsList = {
['Axe'] = '[[File:Bronze axe.png|link=Axe]]',
['Watering can'] = '[[File:Watering can(8).png|link=Watering can]]',
}
local facilitiesIcons = {
['Altar (Zalcano)'] = '[[File:Altar (Zalcano\'s prison) icon.png|link=Altar (Zalcano)]]',
['Anvil'] = '[[File:Anvil icon.png|link=Anvil]]',
['Apothecary'] = '[[File:Apothecary icon.png|link=Apothecary]]',
['Banner easel'] = '[[File:Banner easel icon.png|link=Banner easel]]',
['Barbarian anvil'] = '[[File:Anvil icon.png|link=Anvil]]',
['Bench with vice'] = '[[File:Bench with vice icon.png|link=Bench with vice]]',
['Bench with lathe'] = '[[File:Bench with lathe icon.png|link=Bench with lathe]]',
['Blast Furnace'] = '[[File:Furnace icon.png|link=Blast Furnace]]',
['Blast furnace'] = '[[File:Furnace icon.png|link=Blast Furnace]]',
['Big Compost Bin'] = '[[File:Farming patch icon.png|link=Big Compost Bin]]',
['Brewery'] = '[[File:Brewery icon.png|link=Brewery]]',
['Clay oven'] = '[[File:Cooking range icon.png|link=Clay oven]]',
['Compost Bin'] = '[[File:Farming patch icon.png|link=Compost Bin]]',
['Cooking range'] = '[[File:Cooking range icon.png|link=Cooking range]]',
['Cooking range (2018 Easter event)'] = '[[File:Cooking range icon.png|link=Cooking range (2018 Easter event)]]',
['Crafting table 1'] = '[[File:Crafting table 1 icon.png|link=Crafting table 1]]',
['Crafting table 2'] = '[[File:Crafting table 2 icon.png|link=Crafting table 2]]',
['Crafting table 3'] = '[[File:Crafting table 3 icon.png|link=Crafting table 3]]',
['Crafting table 4'] = '[[File:Crafting table 4 icon.png|link=Crafting table 4]]',
['Dairy churn'] = '[[File:Dairy churn icon.png|link=Dairy churn]]',
['Dairy cow'] = '[[File:Dairy cow icon.png|link=Dairy cow]]',
['Demon lectern'] = '[[File:Demon lectern icon.png|link=Demon lectern]]',
['Eagle lectern'] = '[[File:Eagle lectern icon.png|link=Eagle lectern]]',
['Eodan'] = '[[File:Tannery icon.png|link=Tannery]]',
['Fancy Clothes Store'] = '[[File:Clothes shop icon.png|link=Fancy Clothes Store]]',
['Farming patch'] = '[[File:Farming patch icon.png|link=Farming/Patch_locations]]',
['Furnace'] = '[[File:Furnace icon.png|link=Furnace]]',
['Furnace (Elemental Workshop)'] = '[[File:Furnace icon.png|link=Furnace (Elemental Workshop)]]',
['Furnace (Zalcano)'] = '[[File:Furnace icon.png|link=Furnace (Zalcano)]]',
['Loom'] = '[[File:Loom icon.png|link=Loom]]',
['Lovakite furnace'] = '[[File:Furnace icon.png|link=Lovakite furnace]]',
['Mahogany demon lectern'] = '[[File:Mahogany demon lectern icon.png|link=Mahogany demon lectern]]',
['Mahogany eagle lectern'] = '[[File:Mahogany eagle lectern icon.png|link=Mahogany eagle lectern]]',
['Metal Press'] = '[[File:Furnace icon.png|link=Metal Press]]',
['Oak lectern'] = '[[File:Oak lectern icon.png|link=Oak lectern]]',
['Oak workbench'] = '[[File:Oak workbench icon.png|link=Oak workbench]]',
['Pluming stand'] = '[[File:Pluming stand icon.png|link=Pluming stand]]',
['Potter\'s Wheel'] = '[[File:Pottery wheel icon.png|link=Potter\'s Wheel]]',
['Pottery Oven'] = '[[File:Pottery wheel icon.png|link=Pottery Oven]]',
['Sawmill'] = '[[File:Sawmill icon.png|link=Sawmill]]',
['Sand pit'] = '[[File:Sandpit icon.png|link=Sand pit]]',
['Sbott'] = '[[File:Tannery icon.png|link=Tannery]]',
['Shield easel'] = '[[File:Shield easel icon.png|link=Shield easel]]',
['Singing bowl'] = '[[File:Singing bowl icon.png|link=Singing bowl]]',
['Spinning wheel'] = '[[File:Spinning wheel icon.png|link=Spinning wheel]]',
['Steel framed workbench'] = '[[File:Steel framed workbench icon.png|link=Steel framed workbench]]',
['Tannery'] = '[[File:Tannery icon.png|link=Tannery]]',
['Taxidermist'] = '[[File:Taxidermist icon.png|link=Taxidermist]]',
['Teak demon lectern'] = '[[File:Teak demon lectern icon.png|link=Teak demon lectern]]',
['Teak eagle lectern'] = '[[File:Teak eagle lectern icon.png|link=Teak eagle lectern]]',
['Thakkrad Sigmundson'] = '[[File:Tannery icon.png|link=Thakkrad Sigmundson]]',
['Water'] = '[[File:Water source icon.png|link=Water]]',
['Whetstone'] = '[[File:Whetstone icon.png|link=Whetstone]]',
['Windmill'] = '[[File:Windmill icon.png|link=Windmill]]',
['Woodcutting stump'] = '[[File:Woodcutting stump icon.png|link=Woodcutting stump]]',
['Wooden workbench'] = '[[File:Wooden workbench icon.png|link=Wooden workbench]]',
['Workbench (Guardians of the Rift)'] = '[[File:Workbench (Guardians of the Rift).png|30px|link=Workbench (Guardians of the Rift)]]',
}
function p.main(frame)
local args = frame:getParent().args
local function cost_to_number(cost_v, name, currencyName)
if currencyName ~= nil then
if cost_v == nil then
return 1
elseif tonumber(commas._strip(cost_v),10) then
return tonumber(commas._strip(cost_v),10)
elseif tonumber(expr(cost_v),10) then
return expr(cost_v)
end
elseif cost_v == nil then
if pcall(function () geprice(name) end) then
return geprice(name)
else
return 0
end
elseif string.lower(cost_v) == 'no' then
return 0
elseif tonumber(commas._strip(cost_v),10) then
return tonumber(commas._strip(cost_v),10)
elseif tonumber(expr(cost_v),10) then
return expr(cost_v)
end
return 0
end
local function mat_list(objType)
local ret_list = {}
for i=1,11,1 do
local mat = args[objType..i]
if mat and params.has_content(mat) then
local name = mat
local txt = params.default_to(args[objType..i..'txt'], nil)
local qty = params.default_to(args[objType..i..'quantity'],'1')
local img = params.default_to(args[objType..i..'pic'], name)..'.png'
local cost_v = args[objType..i..'cost']
local currencyName = params.default_to(args[objType..i..'currency'], nil)
local itemnote = args[objType..i..'itemnote'] or nil
local costnote = args[objType..i..'costnote'] or nil
local qtynote = args[objType..i..'quantitynote'] or nil
local subtxt = args[objType..i..'subtxt'] or nil
table.insert(ret_list, {
name = name,
txt = txt,
cost = cost_to_number(cost_v, name, currencyName),
quantity = qty,
image = string.format('[[File:%s|link=%s]]', img, mat),
currency_name = currencyName,
outputnote = itemnote,
quantitynote = qtynote,
subtxt = subtxt,
costnote = costnote
} )
end
end
return ret_list
end
local function skill_list()
local ret_list = {}
for i=1,10,1 do
local skill = args['skill'..i]
if skill and params.has_content(skill) then
local name = skill
local lvl = params.default_to(args['skill'..i..'lvl'],'?')
local boost = params.default_to(args['skill'..i..'boostable'],'')
local exp = commas._strip(params.default_to(args['skill'..i..'exp'],'?'))
table.insert(ret_list, {
name = name,
level = lvl,
boostable = boost,
experience = exp,
} )
end
end
return ret_list
end
local output = mat_list('output')
local materials = mat_list('mat')
local skills = skill_list()
local members = ''
if params.has_content(args.members) then
members = yesno(args.members, true)
end
local useSmw = true
if params.has_content(args.smw) then
useSmw = yesno(args.smw:lower(), true)
end
return p._main(frame, args, args.tools, skills, members, args.notes, materials, output, args.facilities, args.ticks, args.ticksnote, useSmw)
end
--
-- Generates an array of table rows based on skills required for the recipe.
--
-- @param skills {array} List of skill requirements generated by skill_list function.
-- @return {array} List of html tr elements for each skill requirement. Empty table if skills is an empty table or nil.
-- @return {bool} True if any skill requirement, other than level 1, is missing a boostable value in skills. False otherwise.
--
local function generate_skills_rows(skills)
local requirements = {}
local unknown_boostable_flag = false
for i, v in ipairs(skills) do
local levelText = v.level == '?' and edit or v.level
-- Determine which boostable flag to add
local boostable = yesno(v.boostable:lower() or nil) -- If v.boostable can't be lowered, boostable is nil. If it can, and isn't an expected value, yesno returns nil, so boostable is nil either way.
if boostable == nil and (tonumber(v.level) or 0) > 1 then
levelText = levelText .. ' <sup title="Unknown whether this requirement is boostable" style="cursor:help; text-decoration: underline dotted;">?</sup>'
unknown_boostable_flag = true
elseif boostable == false then
levelText = levelText .. ' <sup title="This requirement is not boostable" style="cursor:help; text-decoration: underline dotted;">(nb)</sup>'
elseif boostable == true then
levelText = levelText .. ' <sup title="This requirement is boostable" style="cursor:help; text-decoration: underline dotted;">(b)</sup>'
end -- if boostable is anything else, the skill level is probably 1 or unknown, so no boostable note is added
local xp = v.experience == '?' and edit or v.experience
local citeText = frame:expandTemplate{
title = 'CiteText',
args = {
text = 'Experience boost',
quote = 'The experience shown is for players on the normal gamemode, without any other [[experience boosts]] active.'
}
}
requirement = mw.html.create('tr')
requirement
:tag('td'):attr('colspan', 2):wikitext(skillpic(v.name, nil, true)):done()
:tag('td'):wikitext(levelText):done()
:tag('td'):wikitext((tonumber(xp) ~= nil and commas._add(xp) or xp) .. " " .. citeText):done()
table.insert(requirements, requirement)
end
return requirements, unknown_boostable_flag
end
--
-- Generates a td element for the ticks required.
--
-- @param frame {table} Frame passed in to main.
-- @param ticks {string|number} One of {nil, '', 'NA', 'Varies', [0-9]+} (case agnostic). Other strings will result in an error.
-- @param ticks_note {string} Custom note to be inserted into tick cell if ticks are varied or have a number value.
-- @return {html td element} A td element holding the number of ticks required, along with a note if applicable.
-- @return {bool} True if ticks_note was added to the td element. False otherwise.
--
local function generate_ticks_cell(frame, ticks, ticks_note)
local has_ref_tag = false
local ticks_cell = mw.html.create('td')
local note = ''
-- Prepare a note if ticks_note is given
if ticks_note ~= nil then
note = frame:extensionTag{ name='ref', content = ticks_note, args = { group='r' } }
end
-- Handle cases where no ticks are added, NA is used, Varies is used, or a number is given (default).
-- Breaks if passed a string for ticks since tonumber produces a nil value.
if (ticks or '') == '' then
ticks_cell:wikitext(edit):done()
elseif string.lower(ticks) == 'na' then
ticks_cell:addClass('table-na'):css({ ['text-align'] = center }):wikitext('N/A'):done()
elseif string.lower(ticks) == 'varies' then
has_ref_tag = true
ticks_cell:wikitext('Varies' .. note):done()
else
local secs = tonumber(ticks, 10) * 0.6
if(note ~= '') then
has_ref_tag = true
end
ticks_cell:attr('title', ticks .. ' ticks (' .. secs .. 's) per action'):wikitext(ticks .. ' (' .. secs .. 's)' .. note):done()
end
return ticks_cell, has_ref_tag
end
--
-- Generates a tr element for the item described by item_data.
--
-- @param frame {table} Frame passed in to main.
-- @param item_data {table} A table representing a single item required or output by the recipe. Single member of a table produced by mat_list.
-- @return {html tr element} A tr element holding all information contained in item_data.
-- @return {int} Total cost of the given amount of this item.
-- @return {bool} True if either an item note, quantity note, or cost note was added to the tr element. False otherwise.
--
local function make_row(frame, item_data)
local classOverride, mat_ttl
local textAlign = 'right'
local has_ref_tag = false
if item_data.currency_name ~= nil then
mat_ttl = currencies(item_data.quantity * item_data.cost, item_data.currency_name)
elseif item_data.cost == 0 then
mat_ttl = 'N/A'
classOverride = 'table-na'
textAlign = 'center'
else
mat_ttl = coins(item_data.quantity * item_data.cost)
end
local name = item_data.txt and string.format('[[%s|%s]]', item_data.name, item_data.txt) or string.format('[[%s]]', item_data.name)
local itemnote = item_data.outputnote and frame:extensionTag{ name = 'ref', content = item_data.outputnote, args = { group = 'r' } } or ''
if (itemnote ~= '') then has_ref_tag = true end
local quantitynote = item_data.quantitynote and frame:extensionTag{ name = 'ref', content = item_data.quantitynote, args = { group = 'r' } } or ''
if (quantitynote ~= '') then has_ref_tag = true end
local costnote
if (item_data.costnote and string.lower(item_data.costnote) == 'calculated') then
local class = string.gsub(name, '%W', '')
costnote = frame:extensionTag{ name = 'ref', content = 'Calculated value given in the cost field (generally based on GE prices of ingredients).', args = { group = 'r' } } or ''
else
costnote = item_data.costnote and frame:extensionTag{ name = 'ref', content = item_data.costnote, args = { group = 'r' } } or ''
end
if (costnote ~= '') then has_ref_tag = true end
costnote = costnote_v or costnote
return mw.html.create('tr')
:tag('td'):wikitext(item_data.image):done()
:tag('td'):wikitext(name .. itemnote):done()
:tag('td'):wikitext(commas._add(item_data.quantity) .. quantitynote):done()
:tag('td'):addClass(classOverride):css({ ['text-align'] = textAlign }):wikitext(mat_ttl .. costnote):done(),
item_data.quantity * item_data.cost,
has_ref_tag
end
--
-- Generates a list of tr elements describing all the items given.
--
-- @param frame {table} Frame passed in to main.
-- @param items {array} A list containing a all items required or output by the recipe. Produced by mat_list.
-- @return {array} A list of tr elements, holding one row for each item in items.
-- @return {table} A table of total prices for each currency used by members of items.
-- @return {bool} True if either an item note, quantity note, or cost note was added to any tr element. False otherwise.
--
local function generate_rows(frame, items)
local currency_costs = {
['Coins'] = 0
}
local has_ref_tag = false
local rows = {}
for i, v in ipairs(items) do
local row, row_cost, has_row_note = make_row(frame, v)
if row_cost ~= 0 then
if v.currency_name ~= nil then
currency_costs[v.currency_name] = (currency_costs[v.currency_name] and currency_costs[v.currency_name] or 0) + v.quantity * v.cost
else
currency_costs['Coins'] = currency_costs['Coins'] + v.quantity * v.cost
end
end
has_ref_tag = has_ref_tag or has_row_note
table.insert(rows, row)
end
return rows, currency_costs, has_ref_tag
end
--
-- Generates a tr element containing all of the total costs in the currencies for items in item_costs.
--
-- @param items {array} A list containing a all items required or output by the recipe. Produced by mat_list.
-- @param item_costs {table} A table of total prices for each currency used by members of items. Produced by generate_rows.
-- @return {html tr element} A tr element holding all costs found in item_costs.
--
function generate_total_cost_row(items, item_costs)
local total_cost_row = mw.html.create('tr')
if #items == 0 then
total_cost_row:tag('td'):attr('colspan','5')
:css({ ['font-style'] = 'italic', ['text-align'] = 'center' }):wikitext('Materials unlisted '..editbutton()):done()
else
local total_cost_breakdown = ''
for i, v in next, item_costs, nil do
total_cost_breakdown = (string.len(total_cost_breakdown) == 0 and total_cost_breakdown or total_cost_breakdown .. '<br />') .. (i == 'Coins' and coins(v) or currencies(v, i))
end
total_cost_row:tag('th'):attr('colspan', 3):css({['text-align'] = 'right'}):wikitext('Total cost'):done()
:tag('td'):css({['text-align'] = 'right'}):wikitext(total_cost_breakdown)
end
return total_cost_row
end
--
-- Generates a tr element containing the difference between output and material costs (in coins).
--
-- @param frame {table} Frame passed in to main.
-- @param ticks {string|number} The number of ticks required to create one output. String or nil values will result in an assumption of 5.
-- @param materials_coins_cost {number} The total cost in coins of the materials.
-- @param outputs_coins_cost {number} The total cost in coins of the outputs.
-- @return {html tr element} A tr element holding the profit from one conversion of materials into outputs.
-- @return {bool} True if a note was added to the profit indicating questionable profits. False otherwise.
--
-- FIXME: It's not clear how the note field is supposed to be used. It's not documented and along with has_ref_tag, doesn't seem to actually ever get set to anything other than '' and false respectively.
function generate_profit_row(frame, ticks, materials_coins_cost, outputs_coins_cost)
local profit = outputs_coins_cost - materials_coins_cost
local note = ''
local has_ref_tag = false
-- Find ticks per action. Assume 5 if nothing else is given.
-- If it takes 0 ticks, set to 1/8 since 8 actions can be performed per tick.
local ticks_per_action = tonumber(ticks) or 5
if ticks_per_action == 0 then
ticks_per_action = 1/8
end
-- Create and populate the table row element
local profit_row = mw.html.create('tr')
profit_row
:tag('th'):attr('colspan', 3):css({['text-align'] = 'right'}):wikitext('Profit'):done()
:tag('td'):css({['text-align'] = 'right'}):wikitext(coins(profit) .. note):done()
return profit_row, has_ref_tag
end
--
-- Main
--
function p._main(frame, args, tools, skills, members, notes, materials, output, facilities, ticks, ticks_note, useSmw)
local function toolImages(t)
local images = {}
if params.is_empty(t) then
return 'None'
end
local spl = mw.text.split(t, ",")
for _, image_i in ipairs(spl) do
image_i = mw.text.trim(image_i)
if toolsList[image_i] then
table.insert(images, toolsList[image_i])
else
table.insert(images, string.format("[[File:%s.png|link=%s]]", image_i, image_i))
end
end
return table.concat(images)
end
local function facilityLinks(f)
local links = {}
if params.is_empty(f) then
return 'None'
end
local spl = mw.text.split(f, ",")
for _, link_i in ipairs(spl) do
if facilitiesIcons[link_i] ~= nil then
table.insert(links, string.format("%s [[%s]]", facilitiesIcons[link_i], link_i))
else
table.insert(links, string.format("[[%s]]", link_i))
end
end
return table.concat(links, "<br />")
end
--------------------------------------------------------------------------------
-- START OF REQUIREMENTS TABLE
-- This table contains skill reqs and xp, quest reqs, members req, and ticks
local requirementsTable = mw.html.create('table')
:addClass('wikitable align-center-2 align-right-3')
:css({ width = '100%',
['margin-bottom'] = '0' })
requirementsTable:tag('caption'):wikitext("Requirements"):done()
-- Skills
local unknown_boostable_flag = false
if #skills ~= 0 then
local skill_requirements = mw.html.create('tr')
skill_requirements
:tag('th'):attr('colspan', 2):wikitext('Skill'):done()
:tag('th'):wikitext('Level'):done()
:tag('th'):wikitext('XP'):done()
skill_requirement_rows, unknown_boostable_flag = generate_skills_rows(skills)
for _, row in ipairs(skill_requirement_rows) do
skill_requirements:node(row)
end
requirementsTable:node(skill_requirements)
end
-- Notes
if notes ~= nil then
requirementsTable:tag('tr')
:tag('td'):attr('colspan', 4):wikitext(notes):done()
end
-- Members and Ticks row
local members_and_ticks_row = mw.html.create('tr')
-- lua var members has historically been either 'Yes', 'No', or '' at this point
-- However it wasn't quite obvious that there could be 3 values which led to the previous comments asking if yesno should be used.
-- Now p.main() leaves the variable as either true, false, or '' instead of converting the true and false to strings 'Yes' and 'No' respectively.
-- This makes it so we can more cleanly and obviously handle the 3 cases here without ambiguity about the string values and whether to use yesno or not.
local membersTemplate = members and "[[File:Member icon.png|center|link=Members]]" or members == false and "[[File:Free-to-play icon.png|center|link=Free-to-play]]" or edit
members_and_ticks_row
:tag('th'):wikitext('Members'):done()
:tag('td'):wikitext(membersTemplate):done()
:tag('th'):attr('title', 'Ticks per action'):wikitext('Ticks'):done()
local ticks_cell, has_ticks_ref_tag = generate_ticks_cell(frame, ticks, ticks_note)
members_and_ticks_row:node(ticks_cell)
requirementsTable:node(members_and_ticks_row)
--Tools and Facilities row
if params.has_content(tools) or params.has_content(facilities) then
local toolImgs = toolImages(tools)
local facilityLnks = facilityLinks(facilities)
requirementsTable:tag('tr')
:tag('th'):wikitext('Tools'):done()
:tag('td'):css({ ['text-align'] = 'center' }):wikitext(toolImgs):done()
:tag('th'):wikitext('Facilities'):done()
:tag('td'):css({ ['text-align'] = 'center' }):wikitext(facilityLnks):done()
end
-- END OF REQUIREMENTS TABLE
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- START OF MATERIALS AND PRODUCTS TABLE
-- Contains materials (item, qty, cost), total cost, products, and profit
-- All rows to be in the materials and products table should be appended to materialsTable
local materialsTable = mw.html.create('table')
:addClass('wikitable align-center-1 align-right-3 align-right-4')
:css({ width = '100%',
['margin-top'] = '0' })
materialsTable:tag('caption'):wikitext("Materials"):done()
-- Table header
materialsTable:tag('tr')
:tag('th'):attr('colspan', 2):wikitext('Item'):done()
:tag('th'):wikitext('Quantity'):done()
:tag('th'):wikitext('Cost'):done()
-- Materials
local material_rows, material_costs, has_material_ref_tag = generate_rows(frame, materials)
for _, row in ipairs(material_rows) do
materialsTable:node(row)
end
-- Total cost
local total_cost_row = generate_total_cost_row(materials, material_costs)
materialsTable:node(total_cost_row)
-- Products
local output_rows, output_cost, has_output_ref_tag = generate_rows(frame, output)
for _, row in ipairs(output_rows) do
materialsTable:node(row)
end
-- Profit
local profit_row, has_profit_ref_tag
if output_cost['Coins'] > 0 then
profit_row, has_profit_ref_tag = generate_profit_row(frame, ticks, material_costs['Coins'], output_cost['Coins'])
materialsTable:node(profit_row)
end
-- END OF MATERIALS AND PRODUCTS TABLE
----------------------------------------------------------------------------
-- Append the two tables a parent div
local parent = mw.html.create('div')
:addClass('recipe-table')
:cssText('width:-moz-fit-content;width:fit-content;')
parent:node(requirementsTable)
parent:node(materialsTable)
-- Set smw stuff
if useSmw then
-- See the comment around line 484 (near the members and ticks row)
-- The members lua var now is one of true, false, or '' to avoid ambiguity around string values 'Yes' and 'No', and a not obvious possibility of the value ''
-- Because string values are expected by smw, we convert the boolean values back to strings here
members = members and 'Yes' or members == false and 'No' or ''
local jsonObject = {skills = skills, members = members, materials = {}, output = output[1], ticks = ticks, facilities = facilities, tools = tools}
local materialNames = {}
for _, v in ipairs(materials) do
table.insert(jsonObject.materials, {name = v.name, quantity = v.quantity})
table.insert(materialNames, v.name)
end
local smwmap = {
['Uses material'] = materialNames,
['Uses tool'] = mw.text.split(tools or '', '%s*,%s*'),
['Uses facility'] = mw.text.split(facilities or '', '%s*,%s*'),
['Is members only'] = members,
['Production JSON'] = mw.text.jsonEncode(jsonObject),
['Is boostable'] = {},
['Uses skill'] = {},
}
for i, v in pairs(smwmap) do
-- trim off any {{!}}foo
if type(v) == 'table' then
for j, w in ipairs(v) do
v[j] = mw.text.split(w, '|')[1]
end
end
end
for _, s in ipairs(skills) do
smwmap[s.name..' level'] = tonumber(s.level)
smwmap[s.name..' experience'] = tonumber(s.experience)
table.insert(smwmap['Uses skill'], s.name)
if yesno(s.boostable, false) then
table.insert(smwmap['Is boostable'], s.name)
end
end
mw.smw.set(smwmap)
end
-- If there are any ref tags, add a Reflist section
local outro = ''
local has_ref_tag = has_ticks_ref_tag or has_material_ref_tag or has_output_ref_tag or has_profit_ref_tag
if has_ref_tag then
outro = '<div class="reflist">\n' .. frame:extensionTag{ name='references', args = { group='r' } } .. '</div>'
end
-- Return div with tables + categories + reflist
return tostring(parent) .. categories(args, skills, unknown_boostable_flag) .. outro
end
function categories(args, skills, unknown_boostable_flag)
if not onmain() then
return ''
end
local cats = {}
if unknown_boostable_flag then
table.insert(cats, '[[Category:Recipes missing boostable]]')
end
local missinglvl = false
local missingexp = false
local nonnumexp = false
for i, s in ipairs(skills) do
if s.name then
table.insert(cats, string.format('[[Category:%s]]', s.name))
end
if string.find(s.level, '?') then
missinglvl = true
end
if string.find(s.experience, '?') then
missingexp = true
elseif tonumber(s.experience) == nil then
nonnumexp = true
end
end
if missinglvl then
table.insert(cats, '[[Category:Missing skill info values]]')
end
if missingexp then
table.insert(cats, '[[Category:Needs experience info]]')
end
if nonnumexp then
table.insert(cats, '[[Category:Pages with non-numeric experience quantity]]')
end
if (args.ticks or '') == '' then
table.insert(cats, '[[Category:Recipes missing ticks]]')
end
if args.tools ~= nil then
table.insert(cats, '[[Category:Recipes that require a tool]]')
end
if args.facilities ~= nil then
table.insert(cats, '[[Category:Recipes that use a facility]]')
end
return table.concat(cats,'')
end
return p