Module:SCValue
From Melvor Idle
This module can be used to get information regarding Slayer Coins related shop purchases. For instance, it calculates for much effective profit there can be gained or lost by buying specific items with SC and selling them for GP.
local p = {}
local Shared = require('Module:Shared')
local Shop = require('Module:Shop')
local Items = require('Module:Items')
local Common = require('Module:Common')
local Number = require('Module:Number')
local Icons = require('Module:Icons')
local function getPurchase(itemName)
local func =
function(purchase, name)
return name == itemName
end
local purchList = Shop.getCategoryPurchases(func, 'Slayer')
if purchList ~= nil and not Shared.tableIsEmpty(purchList) then
return purchList[1]
end
end
local function getPurchaseValue(purchase)
if purchase == nil or purchase.cost == nil or purchase.contains == nil
then return 0 end
local costs = purchase.cost
local sales = purchase.contains
local function getItemValues(items)
local gpVal = 0
if items ~= nil then
for _, item in pairs(items) do
gpVal = gpVal + Items.getItemValueByID(item['id']) * item['quantity']
end
end
return gpVal
end
-- Get total costs (including gp/item costs)
local gpCost = 0
if costs.gp ~= nil then gpCost = costs.gp['cost'] or 0 end
gpCost = gpCost + getItemValues(costs.items)
-- Get gross profit from sale
local gpProfit = getItemValues(sales.items)
-- Calculate actual profit
return gpProfit - gpCost
end
local function getSellablePurchases(checkFunc)
local func =
function(purchase, name)
-- Exclude SC Purchases that provide no items.
local items = purchase.contains.items
if items == nil or Shared.tableIsEmpty(items) then
return false
end
if checkFunc == nil then
return true
end
return checkFunc(purchase)
end
return Shop.getCategoryPurchases(func, 'Slayer')
end
local function getMostProfitablePurchases(amount, includeOnlyBulk)
amount = tonumber(amount)
if includeOnlyBulk == nil then includeOnlyBulk = true end
local func = function(x)
if includeOnlyBulk == true then
return x.allowQuantityPurchase == true
else
return true
end
end
local data = {}
-- Gather value data about SC Shop Items
for _, v in pairs(getSellablePurchases(func)) do
local gpValue = getPurchaseValue(v)
local scCost = (v.cost.slayerCoins or {}).cost or 0
local gpPersc = (scCost ~= 0) and (gpValue / scCost) or (gpValue == 0 and 0 or 0)
table.insert(data, {
Purchase = v,
SCCost = scCost,
GPValue = gpValue,
GPPerSC = gpPersc,
})
end
-- Sort by most profitable to least profitable
table.sort(data, function(a, b) return a.GPPerSC > b.GPPerSC end)
-- Keep top x most profitable entries only
if amount ~= nil then
local entries = {}
for i = 1, math.min(#data, amount) do table.insert(entries, data[i]) end
return entries
end
return data
end
function p.getSCItemProfits(frame)
local args = frame:getParent().args
return p._getSCItemProfits(args[1], args[2] or true)
end
function p._getSCItemProfits(amount, includeOnlyBulk)
local purchases = getMostProfitablePurchases(amount, includeOnlyBulk)
local html = mw.html.create('table')
:addClass('wikitable sortable stickyHeader')
html:tag('tr')
:tag('th'):attr('colspan', 2)
:wikitext('Purchase')
:tag('th'):wikitext('Cost')
:tag('th'):wikitext('Requirements')
:tag('th'):wikitext('GP Value')
:tag('th'):wikitext('GP per SC')
for _, v in pairs(purchases) do
local purchase = v.Purchase
local name = Common.getPurchaseName(purchase)
local expansionIcon = Shop._getPurchaseExpansionIcon(purchase)
local costs = Shop.getCostString(purchase.cost, false)
html:tag('tr')
:tag('td'):addClass('table-img')
:wikitext(Common.getPurchaseIcon({purchase, notext=true, size='50'}))
:tag('td'):attr('data-sort-value', name)
:wikitext(expansionIcon)
:wikitext(Common.getPurchaseIcon({purchase, noicon=true}))
:tag('td'):attr('data-sort-value', v.SCCost)
:css('text-align', 'right')
:wikitext(costs)
:tag('td'):wikitext(Common.getRequirementString(purchase.purchaseRequirements, 'None'))
:tag('td'):attr('data-sort-value', v.GPValue)
:css('text-align', 'right')
:wikitext(Icons.GP(v.GPValue))
:tag('td'):attr('data-sort-value', v.GPPerSC)
:css('text-align', 'right')
:wikitext(Icons.GP(Number.autoround(v.GPPerSC)))
end
return tostring(html)
end
function p.getSCValue(frame)
local args = frame:getParent().args
return p._getItemSellsFor(args[1], args[2], args.round)
end
function p._getSCValue(itemName, multiplier, rounding)
local purchase = getPurchase(itemName)
if purchase == nil then
return Shared.printError("No Slayer Shop item exists with the name: " .. itemName)
end
local itemValue = getPurchaseValue(purchase)
multiplier = tonumber(multiplier) or 1
rounding = tonumber(rounding) or 0
return Number.round2(itemValue * multiplier, rounding)
end
function p.test()
mw.logObject(getPurchase("Magical Ring"))
end
return p