Module:Sandbox/User:Alsang: Difference between revisions

From Brighter Shores Wiki
Jump to navigation Jump to search
Content added Content deleted
No edit summary
No edit summary
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
require('strict')
require('Module:Mw.html extension')
require('Module:Mw.html extension')
local Array = require('Module:Array')
local param = require( 'Module:Paramtest' )
local currency = require('Module:Currency').parse
local currency = require('Module:Currency')
local yesno = require('Module:Yesno')
local lang = mw.getContentLanguage()
local purge = require('Module:Purge')._purge
local xpdata = mw.loadData('Module:Experience/data')


local p = {}
local p = {}


-- non dynamic module, no inputs
function p.main(frame)
function p.main()
return p._main(frame:getParent().args)
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)


return p.displayTable(results)
local function recipe_sort(recipe_a, recipe_b)
-- Sort unknown levels to the end
--for debugging
if (recipe_a.level == nil) ~= (recipe_b.level == nil) then
--return '<pre>'..mw.text.jsonEncode(results, mw.text.JSON_PRETTY)..'</pre>'
return recipe_b.level == nil
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


-- goes through a list of results and culls the ones which are not needed for this table
function p._main(args)
function p.screenResults(results)
args = args or {}
local resultsScreened = {}
local item = args[1] or mw.title.getCurrentTitle().text
local showPrices = yesno(args.showPrices)
-- iterate through products
local showValues = yesno(args.showValues)
for _, item in ipairs(results) do
local limit = tonumber(args.limit or 0) or 0
if limit <= 0 then
-- if theres only one activity, wrap in table
limit = 500
if type(item.activityJSON)=='string' then
end
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 _, json in ipairs(jsons) do
for j,json in ipairs(item.activityJSON) do
local json = mw.text.jsonDecode(json)
local activityJSON = mw.text.jsonDecode(json)
json.Value = product.Value
-- Filter out when this item isn't actually used (Will happen on pages with multiple recipes)
if activityJSON.duration and tonumber(activityJSON.duration)==20 then
-- if Array.any(json.materials, function(mat) -- Bypass this for now will need to address this before going live
-- return mat.name == item
local itemNew = {}
itemNew.name = item.name
-- end) then
itemNew.XP = activityJSON.xp
table.insert(parsed, json)
itemNew.lvl = activityJSON.level
-- end
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
table.sort(parsed, recipe_sort)
table.insert(produced_items, parsed)
end
end

-- Sort by the smallest recipe in the group
-- sort the results by recipe level
table.sort(produced_items, function(item1, item2)
table.sort(resultsScreened, function(item1, item2)
local first1 = item1[1]
local lvl1 = item1.lvl
local first2 = item2[1]
local lvl2 = item2.lvl
if (first1 == nil) ~= (first2 == nil) then
if (lvl1 == nil) ~= (lvl2 == nil) then --one of two are empty
return lvl2 == nil -- true if lvl2 is nil but not lvl1, false if lvl1 is nil but not lvl2
return first2 == nil
end
end
if first1 == nil then
if lvl1 == 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)


return resultsScreened
-- Flatten into a single list
local recipes = {}
for _, product in ipairs(produced_items) do
for _, json in ipairs(product) do
table.insert(recipes, json)
end
end


end
-- Calculate shop prices
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
-- make the table
function p.displayTable(results)
local out = mw.html.create('table')
local out = mw.html.create('table')
:addClass('wikitable align-right-1 sortable')
:addClass('wikitable sortable')
:tag('tr')
:tag('tr')
:tag('th')
:tag('th')
:attr{ colspan = '3' }
:wikitext('Page')
:wikitext('Recipe')
:done()
:done()
:tag('th'):wikitext('Level'):done()
:tag('th')
:IF(showValues)
:wikitext('Product')
:tag('th'):wikitext('Value'):done()
:done()
:END()
:tag('th')
:tag('th'):wikitext('Ingredients'):done()
:wikitext('Profession')
:IF(showPrices)
:done()
:tag('th'):wikitext('Price'):done()
:tag('th')
:END()
:wikitext('Level')
: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 _, recipe in ipairs(recipes) do
for i, item in ipairs(results) do
local row = out:tag('tr')
local row = out:tag('tr')
--level
:tag('td')
:tag('td')
:wikitext(item.name)
:css{ ['border-right'] = '0', ['padding-right'] = '0' }
:attr{ ['data-sort-value'] = recipe.output[1].name }
:wikitext(recipe.output[1].quantity .. ' &times;')
:done()
:done()
:tag('td')
:tag('td')
:wikitext('[[' .. item.product .. ']]')
:addClass('plinkt-image no-border')
: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')
:wikitext('[[' .. item.profession .. ']]')
:addClass('plinkt-link no-border')
:wikitext('[[' .. recipe.output[1].name .. ']]')
:done()
:done()
:tag('td')
:tag('td')
:IF(recipe.profession)
:wikitext(item.lvl)
: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')

:wikitext(item.XP)
if showValues then
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 &times; [[File:%s.png|link=%s|18px]] [[%s]]'):format(item.quantity, item.name, item.name, item.name))
:done()
:done()
:tag('td')
end
:wikitext(item.fitXP)

:done()
if showPrices then
local prices = row:tag('td')
:tag('td')
:wikitext(item.productSellPrice)
:tag('ul')
:done()
:css{ ['list-style'] = 'none', ['margin'] = '0', ['padding-left'] = '0' }
-- :tag('td')

-- :wikitext(item.duration)
for _, item in ipairs(recipe.materials) do
-- :done()
if item.price then
-- :tag('td')
prices:tag('li'):wikitext(currency(item.price)):done()
-- :wikitext(item.XPperHour)
else
-- :done()
prices:tag('li'):wikitext('Unknown'):done()
end
end
end


:done()
end
end



Latest revision as of 00:51, 18 December 2024

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.
Module:Sandbox/User:Alsang requires Module:Currency.
Module:Sandbox/User:Alsang requires Module:Mw.html extension.
Module:Sandbox/User:Alsang requires Module:Paramtest.
Module:Sandbox/User:Alsang requires strict.
Module:Sandbox/User:Alsang loads data from Module:Experience/data.

require('strict')
require('Module:Mw.html extension')
local param = require( 'Module:Paramtest' )
local currency = require('Module:Currency')
local lang = mw.getContentLanguage()
local xpdata = mw.loadData('Module:Experience/data')

local p = {}

-- non dynamic module, no inputs
function p.main()
	
	-- 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)

	return p.displayTable(results)
	
	--for debugging
	--return '<pre>'..mw.text.jsonEncode(results, mw.text.JSON_PRETTY)..'</pre>'

end

-- goes through a list of results and culls the ones which are not needed for this table
function p.screenResults(results)
	local resultsScreened = {}
	
	-- iterate through products
	for _, item in ipairs(results) do
		
		-- if theres only one activity, wrap in table
		if type(item.activityJSON)=='string' then
			item.activityJSON = { item.activityJSON }
		end
		
		for j,json in ipairs(item.activityJSON) do
		
			local activityJSON = mw.text.jsonDecode(json)
			
			if activityJSON.duration and tonumber(activityJSON.duration)==20 then
				local itemNew = {}
				itemNew.name = item.name
				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
	
	-- sort the results by recipe level
	table.sort(resultsScreened, function(item1, item2)
		local lvl1 = item1.lvl
		local lvl2 = item2.lvl
		if (lvl1 == nil) ~= (lvl2 == nil) then --one of two are empty
			return lvl2 == nil -- true if lvl2 is nil but not lvl1, false if lvl1 is nil but not lvl2
		end
		if lvl1 == nil then
			return false  -- Both empty, equivalent
		end
		return lvl1 < lvl2 -- normal comparison
	end)

	return resultsScreened

end

-- make the table
function p.displayTable(results)
	local out = mw.html.create('table')
		:addClass('wikitable sortable')
		:tag('tr')
			:tag('th')
				:wikitext('Page')
			:done()
			:tag('th')
				:wikitext('Product')
			:done()
			:tag('th')
				:wikitext('Profession')
			:done()
			:tag('th')
				:wikitext('Level')
			: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()

	for i, item in ipairs(results) do
		local row = out:tag('tr')
		
			--level
			:tag('td')
				:wikitext(item.name)
			:done()
			:tag('td')
				:wikitext('[[' .. item.product .. ']]')
			:done()
			:tag('td')
				:wikitext('[[' .. item.profession .. ']]')
			:done()
			:tag('td')
				:wikitext(item.lvl)
			:done()
			:tag('td')
				:wikitext(item.XP)
			:done()
			:tag('td')
				:wikitext(item.fitXP)
			:done()
			:tag('td')
				:wikitext(item.productSellPrice)
			:done()
--			:tag('td')
--				:wikitext(item.duration)
--			:done()
--			:tag('td')
--				:wikitext(item.XPperHour)
--			:done()

		:done()
	end

	return out
end

return p