Module:Sandbox/User:Alsang: Difference between revisions
Jump to navigation
Jump to search
Content added Content deleted
(set up for passive LW, with both recipes and activities) |
No edit summary |
||
(85 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
p = {} |
|||
require('strict') |
|||
require('Module:Mw.html extension') |
|||
local recipe = require('Module:Infobox Recipe') -- to make use of its extensive material searching function |
|||
local param = require( 'Module:Paramtest' ) |
|||
local currency = require('Module:Currency') |
|||
local discount = require('Module:MerchantHideDiscount') |
|||
local lang = mw.getContentLanguage() |
|||
p.query = '[[Category:Guardian Equipment]] AND [[Variant type::~*]] AND [[Category:Armorer]]|?#-=name|limit=500' |
|||
local p = {} |
|||
-- non dynamic module, no inputs |
|||
function p.main() |
function p.main() |
||
-- returns only directly needed parameter needed for the row, |
|||
local results = mw.smw.ask(p.query) |
|||
-- other parameters are determined by subqueries of chained pages |
|||
local out = mw.html.create('table') |
|||
-- this is in testing, uncomment out one line to test that type of query |
|||
:addClass('wikitable sortable') |
|||
-- requires pages to be made and have recipes on them or it tends to get an error |
|||
for _,page in ipairs(results) do |
|||
-- query types that include non-recipe passive activities behave weird and need to be fixed |
|||
out:tag('tr') |
|||
local query = { |
|||
:tag('th') |
|||
--'[[Uses facility::One Handed Range (bonewright)||One Handed Melee Workbench (bonewright)||Two Handed Range Workbench (bonewright)||Two Handed Melee Workbench (bonewright)||Shield Vice (bonewright)]]', -- bonewright active |
|||
:wikitext('[[' .. page.name .. ']]') |
|||
--'[[Uses facility::Knickknacks workbench]] OR [[Variant of::Divination||Sabertooth Cat Skeleton||Wooly Mammoth Skeleton||Triceratops Skeleton||T-Rex Skeleton||Wendigo Skeleton||Bonemeal Cement]]', -- bonewright passive |
|||
:done() |
|||
--'[[Uses facility::One Handed Range (stonemason)||One Handed Melee Workbench (stonemason)||Two Handed Range Workbench (stonemason)||Two Handed Melee Workbench (stonemason)||Shield Vice (stonemason)]]', -- stonemason active |
|||
:tag('td') |
|||
--'[[Uses facility::Stoneware bench]] OR [[Variant of::Statue Sculpture||Ornamental Scuplture||Column Sculpture||Bust Sculpture]]', -- stonemason passive |
|||
:wikitext('[[' .. page.name .. ' (basic)]]') |
|||
--'[[Uses facility::Goblin Forge||Gnome Forge (skill node)]]', -- blacksmith active |
|||
:done() |
|||
--'[[Uses facility::Jewelry Bench]]', -- blacksmith passive, no non-recipe |
|||
:tag('td') |
|||
'[[-Sold item.Sold by::Leather Goods]] OR [[Variant of::Upholstery]]', -- leatherworker passive, but the Upholstery activities dont have pages yet |
|||
:wikitext('[[' .. page.name .. ' (moderate)]]') |
|||
'?Variant of #- = variant', |
|||
:done() |
|||
'?Profession Level A = lvl', |
|||
:tag('td') |
|||
'? #- = name', |
|||
:wikitext('[[' .. page.name .. ' (fine)]]') |
|||
'?Recipe JSON = recipeJSON', |
|||
:done() |
|||
'?Activity XP = XP', |
|||
:tag('td') |
|||
'?Activity duration = duration', |
|||
:wikitext('[[' .. page.name .. ' (strong)]]') |
|||
'?Value = sell', |
|||
:done() |
|||
'?Activity coins = coins', |
|||
:tag('td') |
|||
'sort = Profession Level A', |
|||
:wikitext('[[' .. page.name .. ' (superior)]]') |
|||
'limit = 500' |
|||
:done() |
|||
} |
|||
:tag('td') |
|||
local results = mw.smw.ask(query) |
|||
:wikitext('[[' .. page.name .. ' (perfect)]]') |
|||
:done() |
|||
-- criterion for if an entry is a recipe, or a passive activity |
|||
:done() |
|||
for _, item in ipairs(results) do |
|||
--item.passiveActivity = false -- can delete this entire FOR statement unless there are non-recipe passive activities on the table |
|||
item.passiveActivity = (item.variant=='Upholstery') -- leatherworker has not got upholstery implemented yet, do not use |
|||
end |
end |
||
return out |
|||
results = p.formatResults(results) |
|||
return p.displayTable(results) |
|||
--for debugging |
|||
--return '<pre>'..mw.text.jsonEncode(results, mw.text.JSON_PRETTY)..'</pre>' |
|||
end |
end |
||
function p.main2() |
|||
-- makes the html for the cells containing currency directly |
|||
-- Replaces nil with an "unknown" cell |
|||
local function currency_cell(amount) |
|||
if not amount then |
|||
return mw.html.create('td') |
|||
:addClass('table-bg-gray') |
|||
:css{ ['text-align'] = 'center' } |
|||
:attr{ colspan = '10' } |
|||
:wikitext("''unknown''") |
|||
:done() |
|||
end |
|||
return currency._cell(amount, { html = 'yes' }) |
|||
end |
|||
-- do calculations and determine strings to go in cells |
|||
function p.formatResults(results) |
|||
local |
local results = mw.smw.ask(p.query) |
||
-- iterate through products |
|||
for _, item in ipairs(results) do |
|||
-- recipe in a workable format |
|||
if item.passiveActivity then |
|||
-- if it is a passive activity that is not a recipe |
|||
-- some fields are easy to work out |
|||
item.outputQuantity = 1 |
|||
item.materials = {} |
|||
item.intermediates = {} |
|||
item.buy = 0 |
|||
item.sell = item.coins |
|||
else |
|||
local unpackJSON = mw.text.jsonDecode(item.recipeJSON) |
|||
item.outputQuantity = unpackJSON.output[1].quantity |
|||
-- call the module:infobox recipe to extensively search for |
|||
-- all raw materials (to add to prices) |
|||
-- all intermediate materials (for intermediate XP and duration) |
|||
local Materials = recipe._getTrueRawMaterials(unpackJSON.materials) |
|||
if next(Materials) ~= nil then |
|||
item.materials = Materials.rawMaterials |
|||
item.intermediates = Materials.intermediateMaterials |
|||
end |
|||
-- iterate through materials, adding buy price to running total (individuals not needed) |
|||
item.buy = 0 |
|||
item.buyDiscount = 0 |
|||
for _, material in ipairs(item.materials) do |
|||
--shamelessley lifted from Module:Products |
|||
local shopPriceQuery = '[[:+]][[Sold item::' .. material.name .. ']]|?Shop buy price|mainlabel=' .. material.name |
|||
local shopPriceResult = mw.smw.ask(shopPriceQuery) or {} |
|||
local shopPrice = 0 |
|||
if shopPriceResult[1] and shopPriceResult[1]["Shop buy price"] then |
|||
shopPrice = tonumber(shopPriceResult[1]["Shop buy price"]) or 0 |
|||
else |
|||
item.buy = nil |
|||
end |
|||
item.buy = item.buy and item.buy + shopPrice * material.quantity |
|||
--with the merchant discount, buy price is sell price |
|||
local shopPriceQuery = '[[:+]][[Sold item::' .. material.name .. ']]|?Shop sell price|mainlabel=' .. material.name |
|||
local shopPriceResult = mw.smw.ask(shopPriceQuery) or {} |
|||
local shopPrice = 0 |
|||
if shopPriceResult[1] and shopPriceResult[1]["Shop sell price"] then |
|||
shopPrice = tonumber(shopPriceResult[1]["Shop sell price"]) or 0 |
|||
else |
|||
item.buyDiscount = nil |
|||
end |
|||
item.buyDiscount = item.buyDiscount and item.buyDiscount + shopPrice * material.quantity |
|||
end |
|||
-- iterate through intermediaries to add to XP and duration parameters |
|||
for _, intermediate in ipairs(item.intermediates) do |
|||
-- look up activity XP and add it to running total |
|||
local XPQuery = '[[Recipe output::' .. intermediate.name .. ']]|?Activity XP|mainlabel=' .. intermediate.name |
|||
local XPResult = mw.smw.ask(XPQuery) or {} |
|||
local XPIncrease = 0 |
|||
if XPResult[1] and XPResult[1]["Activity XP"] then |
|||
XPIncrease = tonumber(XPResult[1]["Activity XP"]) or 0 |
|||
else |
|||
XPIncrease = nil |
|||
end |
|||
-- need to look up both the amount of the item used in this recipe and created in its own recipe to know how much of this xp to use |
|||
local QTYused = intermediate.quantity |
|||
local QTYQuery = '[[Recipe output::' .. intermediate.name .. ']]|?Recipe JSON|mainlabel=' .. intermediate.name |
|||
local QTYResult = mw.smw.ask(QTYQuery) or {} |
|||
local QTYmade = 0 |
|||
if QTYResult[1] and QTYResult[1]["Recipe JSON"] then |
|||
QTYmade = mw.text.jsonDecode(QTYResult[1]["Recipe JSON"]) or {} |
|||
end |
|||
QTYmade = QTYmade.output[1].quantity |
|||
item.XP = item.XP and XPIncrease and item.XP + XPIncrease * QTYused / QTYmade; |
|||
-- look up activity duration and add it to running total |
|||
local durationQuery = '[[Recipe output::' .. intermediate.name .. ']]|?Activity duration|mainlabel=' .. intermediate.name |
|||
local durationResult = mw.smw.ask(durationQuery) or {} |
|||
local durationIncrease = 0 |
|||
if durationResult[1] and durationResult[1]["Activity duration"] then |
|||
durationIncrease = tonumber(durationResult[1]["Activity duration"]) or 0 |
|||
else |
|||
durationIncrease = nil |
|||
end |
|||
item.duration = item.duration and durationIncrease and item.duration + durationIncrease * intermediate.quantity |
|||
end |
|||
end |
|||
-- direct values |
|||
item.sell = item.sell and item.outputQuantity and item.sell * item.outputQuantity |
|||
item.profit = item.sell and item.buy and item.sell - item.buy |
|||
item.profitDiscount = item.sell and item.buyDiscount and item.sell - item.buyDiscount |
|||
item.profitPerXP = item.profit and item.XP and math.floor(item.profit / item.XP * 100) / 100 |
|||
item.profitPerXPDiscount = item.profitDiscount and item.XP and math.floor(item.profitDiscount / item.XP * 100) / 100 |
|||
local hideName = string.gsub(item.name,'Leather','Hide') |
|||
item.discountLevel = discountList[hideName] |
|||
-- a lot of downtime in leatherworker |
|||
-- 1min 40s to go from hide stall to tannery, run round the tannery, run to leather stall, then back to hide stall |
|||
local batchSize = 24 |
|||
local downtime = 100 |
|||
item.duration = item.duration and item.duration + downtime/batchSize |
|||
item.productPerHour = item.duration and 1 / item.duration * 3600 |
|||
-- properties per hour |
|||
item.XPPerHour = item.XP and item.productPerHour and math.floor(item.XP * item.productPerHour) |
|||
item.profitPerHour = item.profit and item.productPerHour and math.floor(item.profit * item.productPerHour) |
|||
item.profitPerHourDiscount = item.profitDiscount and item.productPerHour and math.floor(item.profitDiscount * item.productPerHour) |
|||
end |
|||
return results |
|||
end |
|||
-- make the table |
|||
function p.displayTable(results) |
|||
local out = mw.html.create('table') |
local out = mw.html.create('table') |
||
:addClass('wikitable sortable') |
:addClass('wikitable sortable') |
||
for _,page in ipairs(results) do |
|||
:tag('tr') |
|||
out:tag('tr') |
|||
:tag('th') |
:tag('th') |
||
:attr{ rowspan = '2' } |
|||
:wikitext('[[File:Leatherworker small icon.png|15px]] Level') |
|||
:wikitext('[[' .. page.name .. ']]') |
|||
:done() |
:done() |
||
:tag(' |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (basic).png]]') |
|||
:attr{ colspan = '3' } |
|||
:wikitext('Product') |
|||
:done() |
:done() |
||
:tag(' |
:tag('td') |
||
:wikitext(' |
:wikitext('[[File:' .. page.name .. ' (moderate).png]]') |
||
:done() |
:done() |
||
:tag(' |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (fine).png]]') |
|||
:attr{ colspan = '10' } |
|||
:wikitext('Buy Value') |
|||
:done() |
:done() |
||
:tag(' |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (strong).png]]') |
|||
:attr{ colspan = '10' } |
|||
:wikitext('Sell Value') |
|||
:done() |
:done() |
||
:tag(' |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (superior).png]]') |
|||
:attr{ colspan = '10' } |
|||
:wikitext('Profit') |
|||
:done() |
:done() |
||
:tag(' |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (perfect).png]]') |
|||
:attr{ colspan = '10' } |
|||
:wikitext('Profit/hr') |
|||
:done() |
:done() |
||
:done() |
|||
:tag('tr') |
|||
-- :wikitext('[[File:Merchant_small_icon.png|18px]] level<br>for discount') |
|||
:tag('td') |
|||
:wikitext('[[File:' .. page.name .. ' (basic) dye.png]]') |
|||
-- :tag('th') |
|||
-- :attr{ colspan = '10' } |
|||
-- :wikitext('Profit/hr with [[File:Merchant_small_icon.png|18px]] discount') |
|||
-- :done() |
|||
:tag('th') |
|||
:wikitext('XP') |
|||
:done() |
:done() |
||
:tag(' |
:tag('td') |
||
:wikitext(' |
:wikitext('[[File:' .. page.name .. ' (moderate) dye.png]]') |
||
:done() |
:done() |
||
:tag('th') |
|||
:attr{ colspan = '10' } |
|||
:wikitext('Coins/XP') |
|||
:done() |
|||
-- :tag('th') |
|||
-- :attr{ colspan = '10' } |
|||
-- :wikitext('Coins/XP with [[File:Merchant_small_icon.png|18px]] discount') |
|||
-- :done() |
|||
:done() |
|||
local unknown_value_cell = mw.html.create('td') |
|||
:addClass('table-bg-gray') |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext("''unknown''") |
|||
for i, item in ipairs(results) do |
|||
local row = out:tag('tr') |
|||
:IF(item.lvl) |
|||
:tag('td') |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext(item.lvl) |
|||
:done() |
|||
:ELSE() |
|||
:node(unknown_value_cell) |
|||
:END() |
|||
:tag('td') |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (fine) dye.png]]') |
|||
:css{ ['border-right'] = '0', ['padding-right'] = '0', ['text-align'] = 'right' } |
|||
:attr{ ['data-sort-value'] = item.name } |
|||
:wikitext(item.outputQuantity .. ' ×') |
|||
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (strong) dye.png]]') |
|||
:addClass('plinkt-image no-border') |
|||
:css{ ['border-left'] = '0', ['padding-left'] = '0' } |
|||
:wikitext('[[File:' .. item.name .. '.png|link=' .. item.name .. '|30px]]') |
|||
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (superior) dye.png]]') |
|||
:addClass('plinkt-link no-border') |
|||
:wikitext('[[' .. item.name .. ']]') |
|||
:done() |
:done() |
||
:IF(not(item.passiveActivity)) |
|||
local materialCell = row:tag('td') |
|||
for i, _ in ipairs(item.materials) do |
|||
materialCell:wikitext(item.materials[i].quantity .. '× [[File:' .. item.materials[i].name .. '.png|30px|link=' .. item.materials[i].name .. ']]' .. '[[' .. item.materials[i].name .. ']]<br>') |
|||
end |
|||
row |
|||
:node(currency_cell(item.buy)) |
|||
:node(currency_cell(item.sell)) |
|||
:ELSE() |
|||
:tag('td') |
:tag('td') |
||
:wikitext('[[File:' .. page.name .. ' (perfect) dye.png]]') |
|||
:addClass('table-na') |
|||
:attr{ colspan = '21' } |
|||
:wikitext('N/A') |
|||
:done() |
:done() |
||
:END() |
|||
:node(currency_cell(item.profit)) |
|||
:node(currency_cell(item.profitPerHour)) |
|||
-- :tag('td') |
|||
-- :css{ ['text-align'] = 'center' } |
|||
-- :wikitext(item.discountLevel) |
|||
-- :done() |
|||
-- :node(currency_cell(item.profitPerHourDiscount)) |
|||
:IF(item.XP) |
|||
:tag('td') |
|||
:wikitext(item.XP and lang:formatNum(tonumber(item.XP))) |
|||
:done() |
|||
:ELSE() |
|||
:node(unknown_value_cell) |
|||
:END() |
|||
:IF(item.XPPerHour) |
|||
:tag('td') |
|||
:wikitext(item.XPPerHour and lang:formatNum(tonumber(item.XPPerHour))) |
|||
:done() |
|||
:ELSE() |
|||
:node(unknown_value_cell) |
|||
:END() |
|||
:node(currency_cell(item.profitPerXP)) |
|||
-- :node(currency_cell(item.profitPerXPDiscount)) |
|||
:done() |
:done() |
||
end |
end |
||
return out |
return out |
||
end |
end |
||
return p |
return p |
Revision as of 20:30, 1 January 2025
Module documentation
This documentation is transcluded from Module:Sandbox/User:Alsang/doc. [edit] [history] [purge]
This module does not have any documentation. Please consider adding documentation at Module:Sandbox/User:Alsang/doc. [edit]
Module:Sandbox/User:Alsang's function main is invoked by Template:Sandbox/User:Alsang.
p = {}
p.query = '[[Category:Guardian Equipment]] AND [[Variant type::~*]] AND [[Category:Armorer]]|?#-=name|limit=500'
function p.main()
local results = mw.smw.ask(p.query)
local out = mw.html.create('table')
:addClass('wikitable sortable')
for _,page in ipairs(results) do
out:tag('tr')
:tag('th')
:wikitext('[[' .. page.name .. ']]')
:done()
:tag('td')
:wikitext('[[' .. page.name .. ' (basic)]]')
:done()
:tag('td')
:wikitext('[[' .. page.name .. ' (moderate)]]')
:done()
:tag('td')
:wikitext('[[' .. page.name .. ' (fine)]]')
:done()
:tag('td')
:wikitext('[[' .. page.name .. ' (strong)]]')
:done()
:tag('td')
:wikitext('[[' .. page.name .. ' (superior)]]')
:done()
:tag('td')
:wikitext('[[' .. page.name .. ' (perfect)]]')
:done()
:done()
end
return out
end
function p.main2()
local results = mw.smw.ask(p.query)
local out = mw.html.create('table')
:addClass('wikitable sortable')
for _,page in ipairs(results) do
out:tag('tr')
:tag('th')
:attr{ rowspan = '2' }
:wikitext('[[' .. page.name .. ']]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (basic).png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (moderate).png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (fine).png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (strong).png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (superior).png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (perfect).png]]')
:done()
:done()
:tag('tr')
:tag('td')
:wikitext('[[File:' .. page.name .. ' (basic) dye.png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (moderate) dye.png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (fine) dye.png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (strong) dye.png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (superior) dye.png]]')
:done()
:tag('td')
:wikitext('[[File:' .. page.name .. ' (perfect) dye.png]]')
:done()
:done()
end
return out
end
return p