Module:AlchemistPassiveList: Difference between revisions
Jump to navigation
Jump to search
Content added Content deleted
m (remove vestigal reference to KP that aren't use any more, add some commenting for how it calculates input price) |
(change code base to match PotionList which uses extensive search for all subreceipes and reagents, but keep it showing non-recipe passive activities) |
||
Line 1: | Line 1: | ||
require('strict') |
|||
require('Module:Mw.html extension') |
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 param = require( 'Module:Paramtest' ) |
||
local currency = require('Module:Currency') |
local currency = require('Module:Currency') |
||
local lang = mw.getContentLanguage() |
local lang = mw.getContentLanguage() |
||
require("Module:Mw.html extension") |
|||
local p = {} |
local p = {} |
||
Line 10: | Line 10: | ||
-- non dynamic module, no inputs |
-- non dynamic module, no inputs |
||
function p.main() |
function p.main() |
||
-- returns only directly needed parameter needed for the row, |
|||
-- other parameters are determined by subqueries of chained pages |
|||
-- returns almost every parameter needed for the row, except buy values for reagents |
|||
local query = { |
local query = { |
||
'[[Uses facility::Passive Potion Station]] OR [[Variant of::Ebsworth Work]]', |
'[[Uses facility::Passive Potion Station]] OR [[Variant of::Ebsworth Work]]', |
||
'?Profession Level A = lvl', |
'?Profession Level A = lvl', |
||
'? #- = name', |
'? #- = name', |
||
'? |
'?Recipe JSON = recipeJSON', |
||
'?Value #- = sell', |
|||
'?Activity coins = coins', |
|||
'?Activity XP = XP', |
'?Activity XP = XP', |
||
'?Activity duration = duration', |
'?Activity duration = duration', |
||
'?Activity coins = coins', |
|||
'?Variant of #- = variant', |
'?Variant of #- = variant', |
||
' |
'?Value = sell', |
||
'sort = Profession Level A', |
|||
'limit = 500' |
|||
} |
} |
||
local results = mw.smw.ask(query) |
local results = mw.smw.ask(query) |
||
results = p.formatResults(results) |
results = p.formatResults(results) |
||
Line 35: | Line 36: | ||
end |
end |
||
-- makes the html for the cells containing currency directly |
-- makes the html for the cells containing currency directly |
||
-- Replaces nil with an "unknown" cell |
|||
local function currency_cell(amount) |
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' }) |
return currency._cell(amount, { html = 'yes' }) |
||
end |
end |
||
Line 43: | Line 53: | ||
function p.formatResults(results) |
function p.formatResults(results) |
||
-- iterate through potions |
|||
for _, item in ipairs(results) do |
|||
-- recipe in a workable format |
|||
-- potions have reagents, but passive ebsworth work does not |
|||
if item.variant=='Ebsworth Work' then |
|||
-- if it is ebsworth work, sub in different fields for the buy and sell values |
|||
item.outputQuantity = 1 |
|||
item.reagents = {} |
|||
item.intermediates = {} |
|||
item.buy = 0 |
item.buy = 0 |
||
item.sell = item.coins |
item.sell = item.coins |
||
else |
else |
||
-- iterate through reagents, adding buy price to running total (individuals not needed) |
|||
-- potions always follow the same format, where the reagents are one level down |
|||
-- if copying this code for another profession, will need to change how you identify the inputs. |
|||
-- starting value 20 is for bottle |
|||
item.buy = 20 |
|||
for j, reagent in ipairs(item.reagents) do |
|||
local unpackJSON = mw.text.jsonDecode(item.recipeJSON) |
|||
--shamelessley lifted from Module:Products |
|||
item.outputQuantity = unpackJSON.output[1].quantity |
|||
local shopPriceQuery = '[[:+]][[Sold item::' .. reagent .. ']]|?Shop buy price|mainlabel=' .. reagent |
|||
local shopPriceResult = mw.smw.ask(shopPriceQuery) or {} |
|||
-- call the module:infobox recipe to extensively search for |
|||
local shopPrice = 0 |
|||
-- 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.reagents = Materials.rawMaterials |
|||
item.intermediates = Materials.intermediateMaterials |
|||
end |
|||
-- iterate through reagents, adding buy price to running total (individuals not needed) |
|||
item.buy = 0 |
|||
for _, reagent in ipairs(item.reagents) do |
|||
--shamelessley lifted from Module:Products |
|||
local shopPriceQuery = '[[:+]][[Sold item::' .. reagent.name .. ']]|?Shop buy price|mainlabel=' .. reagent.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 * reagent.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.profitPerXP = item.profit and item.XP and math.floor(item.profit / item.XP * 100) / 100 |
|||
-- potions made in 200 lots of 0.005, no downtime for passive activities |
|||
if shopPriceResult[1] and shopPriceResult[1]["Shop buy price"] then |
|||
local batchSize = 200 |
|||
shopPrice = tonumber(shopPriceResult[1]["Shop buy price"]) or 0 |
|||
local downtime = 0 |
|||
end |
|||
item.duration = item.duration and item.duration + downtime/batchSize |
|||
item.potionPerHour = item.duration and 1 / item.duration * 3600 |
|||
item.buy = item.buy + shopPrice |
|||
end |
|||
-- properties per hour |
|||
end |
|||
item.XPPerHour = item.XP and item.potionPerHour and math.floor(item.XP * item.potionPerHour) |
|||
item.profitPerHour = item.profit and item.potionPerHour and math.floor(item.profit * item.potionPerHour) |
|||
-- sanitise data, set to 0 if its not there |
|||
local lvl = item.lvl or '?' |
|||
local buy = item.buy or 0 |
|||
local sell = item.sell or 0 |
|||
local XP = item.XP or 0 |
|||
local duration = item.duration or 0 |
|||
-- flags for if data values should be shown |
|||
item.hasLvl = param.has_content(item.lvl) |
|||
item.hasBuy = param.has_content(item.buy) |
|||
item.hasSell = param.has_content(item.sell) |
|||
item.hasProfit = item.hasBuy and item.hasSell |
|||
item.hasXP = param.has_content(item.XP) |
|||
item.hasDuration = param.has_content(item.duration) |
|||
-- direct values |
|||
if item.variant=='Ebsworth Work' then |
|||
item.profit = sell - buy |
|||
else |
|||
item.profit = (sell - buy)*0.005 -- passive potions all have quantity 0.005 per action |
|||
end |
|||
item.XP = XP |
|||
if item.XP==0 then |
|||
item.profitPerXP = 0 |
|||
else |
|||
item.profitPerXP = math.floor(item.profit / (item.XP) * 100) / 100 |
|||
end |
|||
-- passive activities have no downtime |
|||
item.duration = duration |
|||
if item.duration == 0 then |
|||
item.potionPerHour = 0 |
|||
else |
|||
item.potionPerHour = 1 / (item.duration) * 3600 |
|||
end |
|||
-- properties per hour |
|||
item.XPPerHour = math.floor(item.XP * item.potionPerHour) |
|||
item.profitPerHour = math.floor(item.profit * item.potionPerHour) |
|||
end |
end |
||
return results |
|||
end |
end |
||
-- make the table |
-- make the table |
||
function p.displayTable(results) |
function p.displayTable(results) |
||
local out = mw.html.create('table') |
|||
local out = mw.html.create('table') |
|||
:addClass('wikitable sortable') |
:addClass('wikitable sortable') |
||
:tag('tr') |
:tag('tr') |
||
Line 129: | Line 168: | ||
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
:attr{ colspan = '3' } |
|||
:wikitext('Potion or Activity') |
|||
:wikitext('Potion') |
|||
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
:wikitext('Reagents |
:wikitext('Reagents') |
||
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
Line 161: | Line 201: | ||
:done() |
:done() |
||
:done() |
:done() |
||
local unknown_value_cell = mw.html.create('td') |
|||
:addClass('table-bg-gray') |
|||
:css{ ['text-align'] = 'center' } |
|||
for i,item in ipairs(results) do |
|||
:wikitext("''unknown''") |
|||
-- if its not ebsworth work, need a list of reagents |
|||
for i, item in ipairs(results) do |
|||
local reagentCell = '' |
|||
local row = out:tag('tr') |
|||
if not(item.variant=='Ebsworth Work') then |
|||
:IF(item.lvl) |
|||
-- need to generate the text for the reagent cell before starting the row |
|||
:tag('td') |
|||
for j, reagent in ipairs(item.reagents) do |
|||
reagentCell = reagentCell .. '[[File:' .. reagent .. '.png|30px|link=' .. reagent .. ']] [[' .. reagent .. ']]<br>' |
|||
end |
|||
end |
|||
out |
|||
:tag('tr') |
|||
:tag('td') |
|||
:IF(item.hasBuy) |
|||
:css{ ['text-align'] = 'center' } |
:css{ ['text-align'] = 'center' } |
||
:wikitext(item.lvl) |
:wikitext(item.lvl) |
||
: |
:done() |
||
:ELSE() |
|||
:addClass('table-bg-grey') |
|||
:node(unknown_value_cell) |
|||
:css{ ['text-align'] = 'center' } |
|||
:END() |
|||
:END() |
|||
:tag('td') |
|||
:css{ ['border-right'] = '0', ['padding-right'] = '0', ['text-align'] = 'right' } |
|||
:attr{ ['data-sort-value'] = item.name } |
|||
:wikitext(item.outputQuantity .. ' ×') |
|||
:done() |
|||
:tag('td') |
|||
:addClass('plinkt-image no-border') |
|||
:css{ ['border-left'] = '0', ['padding-left'] = '0' } |
|||
:wikitext('[[File:' .. item.name .. '.png|link=' .. item.name .. '|30px]]') |
|||
:done() |
|||
:tag('td') |
|||
:addClass('plinkt-link no-border') |
|||
:wikitext('[[' .. item.name .. ']]') |
|||
:done() |
:done() |
||
:IF(not(item.variant=='Ebsworth Work')) |
|||
local reagentCell = row:tag('td') |
|||
for i, _ in ipairs(item.reagents) do |
|||
reagentCell:wikitext(item.reagents[i].quantity .. '× [[File:' .. item.reagents[i].name .. '.png|18px|link=' .. item.reagents[i].name .. ']]' .. '[[' .. item.reagents[i].name .. ']]<br>') |
|||
end |
|||
row |
|||
:node(currency_cell(item.buy)) |
|||
:node(currency_cell(item.sell)) |
|||
:ELSE() |
|||
:tag('td') |
:tag('td') |
||
:addClass('table-na') |
|||
:wikitext('[[File:' .. item.name .. '.png|30px|link=' .. item.name .. ']] [[' .. item.name .. ']]') |
|||
:attr{ colspan = '21' } |
|||
:wikitext('N/A') |
|||
:done() |
:done() |
||
:END() |
|||
:IF(not(item.variant=='Ebsworth Work')) |
|||
:node(currency_cell(item.profit)) |
|||
:node(currency_cell(item.profitPerHour)) |
|||
:IF(item.XP) |
|||
:tag('td') |
:tag('td') |
||
:wikitext( |
:wikitext(item.XP and lang:formatNum(tonumber(item.XP))) |
||
:done() |
:done() |
||
:IF(item.hasBuy) |
|||
:node(currency_cell(item.buy)) |
|||
:ELSE() |
|||
:tag('td') |
|||
:addClass('table-bg-grey') |
|||
:attr{ colspan = '10' } |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext('unknown') |
|||
:done() |
|||
:END() |
|||
:IF(item.hasSell) |
|||
-- I cannot for the life of me figure out why, |
|||
-- but if I put item.sell directly into this function it claims it has value nil |
|||
-- it works for other functions to display it directly |
|||
-- so here is the workaround I guess |
|||
:node(currency_cell(item.buy+200*item.profit)) |
|||
--:node(currency_cell(item.sell)) |
|||
:ELSE() |
|||
:tag('td') |
|||
:addClass('table-bg-grey') |
|||
:attr{ colspan = '10' } |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext('unknown') |
|||
:done() |
|||
:END() |
|||
:ELSE() |
:ELSE() |
||
: |
:node(unknown_value_cell) |
||
:addClass('table-na') |
|||
:attr{ colspan = '21' } |
|||
:wikitext('N/A') |
|||
:done() |
|||
:END() |
:END() |
||
:IF(item. |
:IF(item.XPPerHour) |
||
:node(currency_cell(item.profit)) |
|||
:ELSE() |
|||
:tag('td') |
:tag('td') |
||
:wikitext(item.XPPerHour and lang:formatNum(tonumber(item.XPPerHour))) |
|||
:addClass('table-bg-grey') |
|||
:attr{ colspan = '10' } |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext('unknown') |
|||
:done() |
:done() |
||
:END() |
|||
:IF(item.hasProfit and item.hasDuration) |
|||
:node(currency_cell(item.profitPerHour)) |
|||
:ELSE() |
:ELSE() |
||
: |
:node(unknown_value_cell) |
||
:addClass('table-bg-grey') |
|||
:attr{ colspan = '10' } |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext('unknown') |
|||
:done() |
|||
:END() |
:END() |
||
:node(currency_cell(item.profitPerXP)) |
|||
:tag('td') |
|||
:IF(item.hasXP) |
|||
:wikitext(item.XP) |
|||
:ELSE() |
|||
:addClass('table-bg-grey') |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext('unknown') |
|||
:END() |
|||
:done() |
|||
:tag('td') |
|||
:IF(item.hasXP and item.hasDuration) |
|||
:wikitext(lang:formatNum(tonumber(item.XPPerHour))) |
|||
:ELSE() |
|||
:addClass('table-bg-grey') |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext('unknown') |
|||
:END() |
|||
:done() |
|||
:IF(item.hasXP and item.hasProfit) |
|||
:node(currency_cell(item.profitPerXP)) |
|||
:ELSE() |
|||
:tag('td') |
|||
:addClass('table-bg-grey') |
|||
:attr{ colspan = '10' } |
|||
:css{ ['text-align'] = 'center' } |
|||
:wikitext('unknown') |
|||
:done() |
|||
:END() |
|||
:done() |
:done() |
||
end |
end |
||
return out |
return out |
||
end |
end |