Editing Module:Sandbox/User:Alsang
Jump to navigation
Jump to search
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
require('strict') |
|||
require('Module:Mw.html extension') |
require('Module:Mw.html extension') |
||
local |
local Array = require('Module:Array') |
||
local currency = require('Module:Currency') |
local currency = require('Module:Currency').parse |
||
local |
local yesno = require('Module:Yesno') |
||
local |
local purge = require('Module:Purge')._purge |
||
local p = {} |
local p = {} |
||
function p.main(frame) |
|||
-- non dynamic module, no inputs |
|||
return p._main(frame:getParent().args) |
|||
function p.main() |
|||
end |
|||
-- returns only directly needed parameter needed for the row, |
|||
-- other parameters are determined by subqueries of chained pages |
|||
local query = { |
|||
'[[Activity JSON::~*]]', |
|||
'? = name', |
|||
'?Activity JSON = activityJSON', |
|||
'limit = 1500' |
|||
} |
|||
local results = mw.smw.ask(query) |
|||
results = p.screenResults(results) |
|||
local function recipe_sort(recipe_a, recipe_b) |
|||
return p.displayTable(results) |
|||
-- Sort unknown levels to the end |
|||
if (recipe_a.level == nil) ~= (recipe_b.level == nil) then |
|||
--for debugging |
|||
return recipe_b.level == nil |
|||
--return '<pre>'..mw.text.jsonEncode(results, mw.text.JSON_PRETTY)..'</pre>' |
|||
end |
|||
if recipe_a.level ~= nil then |
|||
return recipe_a.level < recipe_b.level |
|||
end |
|||
-- Sort by name if same level |
|||
return recipe_a.output[1].name < recipe_b.output[1].name |
|||
end |
end |
||
function p._main(args) |
|||
-- goes through a list of results and culls the ones which are not needed for this table |
|||
args = args or {} |
|||
function p.screenResults(results) |
|||
local item = args[1] or mw.title.getCurrentTitle().text |
|||
local resultsScreened = {} |
|||
local showPrices = yesno(args.showPrices) |
|||
local showValues = yesno(args.showValues) |
|||
-- iterate through products |
|||
local limit = tonumber(args.limit or 0) or 0 |
|||
for _, item in ipairs(results) do |
|||
if limit <= 0 then |
|||
limit = 500 |
|||
-- if theres only one activity, wrap in table |
|||
end |
|||
if type(item.activityJSON)=='string' then |
|||
item.activityJSON = { item.activityJSON } |
|||
-- Query for data |
|||
local smw_data = mw.smw.ask{ |
|||
'[[Activity Input::' .. item .. ']]', |
|||
'?Activity Input', |
|||
'?Activity JSON', |
|||
showValues and '?Value', |
|||
limit = limit |
|||
} |
|||
if not smw_data then |
|||
return ":''No products found. To force an update, click " |
|||
..purge('dml-'..mw.uri.anchorEncode(item), 'here', 'span') |
|||
..".''[[Category:Empty products lists]]" |
|||
end |
|||
-- Create a list of all recipes, grouped by output item (to keep them together in the sort) |
|||
local produced_items = {} |
|||
for _, product in ipairs(smw_data) do |
|||
local jsons = product['Activity JSON'] |
|||
if type(jsons) == 'string' then |
|||
jsons = { jsons } |
|||
end |
end |
||
local parsed = {} |
|||
for |
for _, json in ipairs(jsons) do |
||
local json = mw.text.jsonDecode(json) |
|||
json.Value = product.Value |
|||
local activityJSON = mw.text.jsonDecode(json) |
|||
-- Filter out when this item isn't actually used (Will happen on pages with multiple recipes) |
|||
if Array.any(json.materials, function(mat) |
|||
if activityJSON.duration and tonumber(activityJSON.duration)==20 then |
|||
return mat.name == item |
|||
end) then |
|||
itemNew.name = item.name |
|||
table.insert(parsed, json) |
|||
itemNew.XP = activityJSON.xp |
|||
itemNew.lvl = activityJSON.level |
|||
itemNew.profession = activityJSON.profession |
|||
itemNew.duration = activityJSON.duration |
|||
itemNew.product = activityJSON.output[1].name |
|||
itemNew.XPperHour = itemNew.XP and tonumber(itemNew.XP) and itemNew.duration and tonumber(itemNew.duration) and tonumber(itemNew.XP) * 3600 / tonumber(itemNew.duration) |
|||
itemNew.fitXP = xpdata.knowledge[itemNew.lvl]*4*0.0005 |
|||
if itemNew.lvl>=200 then |
|||
itemNew.fitXP = itemNew.fitXP * 4 |
|||
end |
|||
itemNew.fitXP = math.floor(itemNew.fitXP * 100 ) / 100 |
|||
local query = mw.smw.ask('[[Sold item::' .. itemNew.product .. ']][[Shop sell price::!~N/A]]|?Shop sell price=data|mainlabel=-') |
|||
if type(query)=='table' then |
|||
-- price is returned as a number |
|||
itemNew.productSellPrice = tonumber(query[1].data)*0.005 |
|||
else |
|||
-- will return nil if the item is not in a shop, or if it is in a shop but can only be sold to the shop |
|||
itemNew.productSellPrice = nil |
|||
end |
|||
table.insert(resultsScreened,itemNew) |
|||
end |
end |
||
end |
end |
||
table.sort(parsed, recipe_sort) |
|||
table.insert(produced_items, parsed) |
|||
end |
end |
||
-- |
-- Sort by the smallest recipe in the group |
||
table.sort( |
table.sort(produced_items, function(item1, item2) |
||
local |
local first1 = item1[1] |
||
local |
local first2 = item2[1] |
||
if ( |
if (first1 == nil) ~= (first2 == nil) then |
||
return first2 == nil |
|||
return lvl2 == nil -- true if lvl2 is nil but not lvl1, false if lvl1 is nil but not lvl2 |
|||
end |
end |
||
if |
if first1 == nil then |
||
return false -- Both empty, equivalent |
return false -- Both empty, equivalent |
||
end |
end |
||
return lvl1 < lvl2 -- normal comparison |
|||
return recipe_sort(first1, first2) |
|||
end) |
end) |
||
-- Flatten into a single list |
|||
return resultsScreened |
|||
local recipes = {} |
|||
for _, product in ipairs(produced_items) do |
|||
for _, json in ipairs(product) do |
|||
table.insert(recipes, json) |
|||
end |
|||
end |
|||
-- Calculate shop prices |
|||
end |
|||
if showPrices then |
|||
local price_cache = {} |
|||
for _, recipe in ipairs(recipes) do |
|||
for _, item in ipairs(recipe.materials) do |
|||
-- Extract item name and quantity from the "item,#" format |
|||
-- Query for the shop buy price of the item |
|||
local shopPriceResult = price_cache[item.name] or mw.smw.ask{ |
|||
'[[Sold item::' .. item.name .. ']]', |
|||
'?Shop buy price' |
|||
} or {} |
|||
price_cache[item.name] = shopPriceResult |
|||
local shopPrice |
|||
if shopPriceResult[1] then |
|||
shopPrice = tonumber(shopPriceResult[1]['Shop buy price'] or 0) or 0 |
|||
end |
|||
-- Update the product with the total price |
|||
if shopPrice ~= nil then |
|||
item.price = shopPrice * item.quantity |
|||
end |
|||
end |
|||
end |
|||
end |
|||
-- |
-- Create table |
||
function p.displayTable(results) |
|||
local out = mw.html.create('table') |
local out = mw.html.create('table') |
||
:addClass('wikitable sortable') |
:addClass('wikitable align-right-1 sortable') |
||
:tag('tr') |
:tag('tr') |
||
:tag('th') |
:tag('th') |
||
: |
:attr{ colspan = '3' } |
||
:wikitext('Recipe') |
|||
:done() |
:done() |
||
:tag('th') |
:tag('th'):wikitext('Level'):done() |
||
:IF(showValues) |
|||
:done() |
:tag('th'):wikitext('Value'):done() |
||
: |
:END() |
||
:tag('th'):wikitext('Ingredients'):done() |
|||
: |
:IF(showPrices) |
||
:tag('th') |
:tag('th'):wikitext('Price'):done() |
||
:END() |
|||
:done() |
|||
:tag('th') |
|||
:wikitext('XP') |
|||
:done() |
|||
:tag('th') |
|||
:wikitext('0.0005 of levelup XP') |
|||
:done() |
|||
:tag('th') |
|||
:wikitext('sell price<br>per action') |
|||
:done() |
|||
-- :tag('th') |
|||
-- :wikitext('Duration') |
|||
-- :done() |
|||
-- :tag('th') |
|||
-- :wikitext('XP/hr') |
|||
-- :done() |
|||
:done() |
:done() |
||
for |
for _, recipe in ipairs(recipes) do |
||
local row = out:tag('tr') |
local row = out:tag('tr') |
||
--level |
|||
:tag('td') |
:tag('td') |
||
:css{ ['border-right'] = '0', ['padding-right'] = '0' } |
|||
:wikitext(item.name) |
|||
:attr{ ['data-sort-value'] = recipe.output[1].name } |
|||
:wikitext(recipe.output[1].quantity .. ' ×') |
|||
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
:addClass('plinkt-image no-border') |
|||
:wikitext('[[' .. item.product .. ']]') |
|||
:css{ ['border-left'] = '0', ['padding-left'] = '0' } |
|||
:wikitext('[[File:' .. recipe.output[1].name .. '.png|link=' .. recipe.output[1].name .. '|30px]]') |
|||
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
:addClass('plinkt-link no-border') |
|||
:wikitext('[[' .. item.profession .. ']]') |
|||
:wikitext('[[' .. recipe.output[1].name .. ']]') |
|||
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
: |
:IF(recipe.profession) |
||
:wikitext(('[[File:%s small icon.png|15px|link=%s]] %s'):format(recipe.profession, recipe.profession, recipe.level or 'Unknown')) |
|||
:ELSE() |
|||
:wikitext(('[[FileUnknown profession small icon.png|15px|link=Professions]] %s'):format(recipe.level or 'Unknown')) |
|||
:END() |
|||
:done() |
:done() |
||
:tag('td') |
|||
if showValues then |
|||
:wikitext(item.XP) |
|||
if recipe.Value then |
|||
row:tag('td') |
|||
:wikitext(currency(recipe.Value)) |
|||
:done() |
|||
else |
|||
row:tag('td') |
|||
:attr{ ['data-sort-value'] = '' } |
|||
:wikitext('Unknown') |
|||
:done() |
|||
end |
|||
end |
|||
local ingredients = row:tag('td') |
|||
:attr{ ['data-sort-value'] = table.concat(Array.map(recipe.materials, function(item) return item.name end), '\0') } |
|||
:tag('ul') |
|||
:css{ ['list-style'] = 'none', ['margin'] = '0', ['padding-left'] = '0' } |
|||
for _, item in ipairs(recipe.materials) do |
|||
ingredients:tag('li') |
|||
:wikitext(('%s × [[File:%s.png|link=%s|18px]] [[%s]]'):format(item.quantity, item.name, item.name, item.name)) |
|||
:done() |
:done() |
||
end |
|||
:tag('td') |
|||
:wikitext(item.fitXP) |
|||
if showPrices then |
|||
:done() |
|||
:tag('td') |
local prices = row:tag('td') |
||
:tag('ul') |
|||
:wikitext(item.productSellPrice) |
|||
:css{ ['list-style'] = 'none', ['margin'] = '0', ['padding-left'] = '0' } |
|||
:done() |
|||
-- :tag('td') |
|||
for _, item in ipairs(recipe.materials) do |
|||
-- :wikitext(item.duration) |
|||
if item.price then |
|||
-- :done() |
|||
prices:tag('li'):wikitext(currency(item.price)):done() |
|||
-- :tag('td') |
|||
else |
|||
-- :wikitext(item.XPperHour) |
|||
prices:tag('li'):wikitext('Unknown'):done() |
|||
-- :done() |
|||
end |
|||
end |
|||
end |
|||
:done() |
|||
end |
end |
||