Anonymous

Module:SCValue: Difference between revisions

From Melvor Idle
Amend for 1.3 currency changes
No edit summary
(Amend for 1.3 currency changes)
 
Line 2: Line 2:


local Shared = require('Module:Shared')
local Shared = require('Module:Shared')
local GameData = require('Module:GameData')
local Shop = require('Module:Shop')
local Shop = require('Module:Shop')
local Items = require('Module:Items')
local Items = require('Module:Items')
Line 9: Line 10:


local function getPurchase(itemName)
local function getPurchase(itemName)
local func =  
local func =
function(purchase, name)
function(purchase, name)
return name == itemName
return name == itemName
Line 20: Line 21:
end
end


local function getPurchaseValue(purchase)
local function getPurchaseValue(purchase, currencyID)
if purchase == nil or purchase.cost == nil or purchase.contains == nil  
if purchase == nil or purchase.cost == nil or purchase.contains == nil
then return 0 end
then return 0 end
 
local costs = purchase.cost
local costs = purchase.cost
local sales = purchase.contains
local sales = purchase.contains
 
local function getItemValues(items)
local function getItemValues(items)
local gpVal = 0
local currVal = 0
if items ~= nil then
if items ~= nil then
for _, item in pairs(items) do
for _, item in ipairs(items) do
gpVal = gpVal + Items.getItemValueByID(item['id']) * item['quantity']
local itemObj = Items.getItemByID(item.id)
local itemCurrencyID = itemObj.sellsForCurrency or 'melvorD:GP'
if itemCurrencyID == currencyID then
currVal = currVal + (itemObj.sellsFor or 0) * item.quantity
end
end
end
end
end
return gpVal
return currVal
end
end
 
-- Get total costs (including gp/item costs)
-- Get total costs (including gp/item costs)
local gpCost = 0
local currCost = 0
if costs.gp ~= nil then gpCost = costs.gp['cost'] or 0 end
if costs ~= nil and costs.currencies ~= nil then
gpCost = gpCost + getItemValues(costs.items)
local purchCurrCost = GameData.getEntityByProperty(costs.currencies, 'currency', currencyID)
if purchCurrCost ~= nil then
currCost = currCost + (purchCurrCost.cost or 0)
end
end


-- Get gross profit from sale
-- Get gross profit from sale
local gpProfit = getItemValues(sales.items)
local currProfit = getItemValues(sales.items)


-- Calculate actual profit
-- Calculate actual profit
return gpProfit - gpCost
return currProfit - currCost
end
end


local function getSellablePurchases(checkFunc)
local function getSellablePurchases(checkFunc)
local func =  
local func =
function(purchase, name)
function(purchase, name)
-- Exclude SC Purchases that provide no items.
-- Exclude SC Purchases that provide no items.
Line 61: Line 70:
return true
return true
end
end
 
return checkFunc(purchase)
return checkFunc(purchase)
end
end
 
return Shop.getCategoryPurchases(func, 'Slayer')
return Shop.getCategoryPurchases(func, 'Slayer')
end
end


local function getMostProfitablePurchases(amount, includeOnlyBulk)
local function getMostProfitablePurchases(amount, gainedCurrencyID, spentCurrencyID, includeOnlyBulk)
amount = tonumber(amount)
amount = tonumber(amount)
if includeOnlyBulk == nil then includeOnlyBulk = true end
if includeOnlyBulk == nil then includeOnlyBulk = true end
 
local func = function(x)
local func = function(x)
if includeOnlyBulk == true then  
if includeOnlyBulk == true then
return x.allowQuantityPurchase == true  
return x.allowQuantityPurchase == true
else
else
return true  
return true
end
end
end
end
local data = {}
local data = {}
-- Gather value data about SC Shop Items
-- Gather value data about Shop Items
for _, v in pairs(getSellablePurchases(func)) do
for _, v in ipairs(getSellablePurchases(func)) do
local gpValue = getPurchaseValue(v)
local gainedValue = getPurchaseValue(v, gainedCurrencyID)
local scCost = (v.cost.slayerCoins or {}).cost or 0
local spentValue = 0
local gpPersc = (scCost ~= 0) and (gpValue / scCost) or (gpValue == 0 and 0 or 0)
if v.cost ~= nil and v.cost.currencies ~= nil then
local spentCurrencyCost = GameData.getEntityByProperty(v.cost.currencies, 'currency', spentCurrencyID)
if spentCurrencyCost ~= nil then
spentValue = spentCurrencyCost.cost or 0
end
end
 
local gainedPerSpent = 0
if gainedValue ~= 0 and spentValue ~= 0 then
gainedPerSpent = gainedValue / spentValue
end
 
table.insert(data, {
table.insert(data, {
Purchase = v,
Purchase = v,
SCCost = scCost,
spentValue = spentValue,
GPValue = gpValue,
gainedValue = gainedValue,
GPPerSC = gpPersc,
gainedPerSpent = gainedPerSpent,
})
})
end
end
 
-- Sort by most profitable to least profitable
-- Sort by most profitable to least profitable
table.sort(data, function(a, b) return a.GPPerSC > b.GPPerSC end)
table.sort(data, function(a, b) return a.gainedPerSpent > b.gainedPerSpent end)


-- Keep top x most profitable entries only
-- Keep top x most profitable entries only
Line 103: Line 122:
return entries
return entries
end
end
 
return data
return data
end
end
Line 109: Line 128:
function p.getSCItemProfits(frame)
function p.getSCItemProfits(frame)
local args = frame:getParent().args
local args = frame:getParent().args
return p._getSCItemProfits(args[1], args[2] or true)
return p._getCurrencyItemProfits(args[1], 'melvorD:GP', 'melvorD:SlayerCoins', args[2] or true)
end
end


function p._getSCItemProfits(amount, includeOnlyBulk)
function p._getCurrencyItemProfits(amount, gainedCurrencyID, spentCurrencyID, includeOnlyBulk)
local purchases = getMostProfitablePurchases(amount, includeOnlyBulk)
local currencyShortNames = {
["melvorD:GP"] = 'GP',
["melvorD:SlayerCoins"] = 'SC',
["melvorD:RaidCoins"] = 'RC',
["melvorItA:AbyssalPieces"] = 'AP',
["melvorItA:AbyssalSlayerCoins"] = 'ASC'
}
local gainedName, spentName = currencyShortNames[gainedCurrencyID], currencyShortNames[spentCurrencyID]
 
if gainedName == nil or spentName == nil then
local unknownID = (
(gainedName == nil and (gainedCurrencyID or 'GainedCurrency'))
or (spentCurrencyID or 'SpentCurrency')
)
return Shared.printError('Unknown currency ID: ' .. unknownID)
end
 
local purchases = getMostProfitablePurchases(amount, gainedCurrencyID, spentCurrencyID, includeOnlyBulk)


local html = mw.html.create('table')
local html = mw.html.create('table')
:addClass('wikitable sortable stickyHeader')
:addClass('wikitable sortable stickyHeader')
 
html:tag('tr')
html:tag('tr')
:tag('th'):attr('colspan', 2)
:tag('th'):attr('colspan', 2)
Line 123: Line 159:
:tag('th'):wikitext('Cost')
:tag('th'):wikitext('Cost')
:tag('th'):wikitext('Requirements')
:tag('th'):wikitext('Requirements')
:tag('th'):wikitext('GP Value')
:tag('th'):wikitext(gainedName .. ' Value')
:tag('th'):wikitext('GP per SC')
:tag('th'):wikitext(gainedName .. ' per ' .. spentName)
 
for _, v in pairs(purchases) do
for _, v in ipairs(purchases) do
local purchase =  v.Purchase
local purchase =  v.Purchase
local name = Common.getPurchaseName(purchase)
local name = Common.getPurchaseName(purchase)
local expansionIcon = Shop._getPurchaseExpansionIcon(purchase)
local expansionIcon = Shop._getPurchaseExpansionIcon(purchase)
local costs = Shop.getCostString(purchase.cost, false)
local costs = Shop.getCostString(purchase.cost, false)
 
html:tag('tr')
html:tag('tr')
:tag('td'):addClass('table-img')
:tag('td'):addClass('table-img')
Line 138: Line 174:
  :wikitext(expansionIcon)
  :wikitext(expansionIcon)
  :wikitext(Common.getPurchaseIcon({purchase, noicon=true}))
  :wikitext(Common.getPurchaseIcon({purchase, noicon=true}))
:tag('td'):attr('data-sort-value', v.SCCost)
:tag('td'):attr('data-sort-value', v.spentValue)
  :css('text-align', 'right')
  :css('text-align', 'right')
  :wikitext(costs)
  :wikitext(costs)
:tag('td'):wikitext(Common.getRequirementString(purchase.purchaseRequirements, 'None'))
:tag('td'):wikitext(Common.getRequirementString(purchase.purchaseRequirements, 'None'))
:tag('td'):attr('data-sort-value', v.GPValue)
:tag('td'):attr('data-sort-value', v.gainedValue)
  :css('text-align', 'right')
  :css('text-align', 'right')
  :wikitext(Icons.GP(v.GPValue))
  :wikitext(Icons._Currency(gainedCurrencyID, v.gainedValue))
:tag('td'):attr('data-sort-value', v.GPPerSC)
:tag('td'):attr('data-sort-value', v.gainedPerSpent)
  :css('text-align', 'right')
  :css('text-align', 'right')
  :wikitext(Icons.GP(Number.autoround(v.GPPerSC)))
  :wikitext(Icons._Currency(gainedCurrencyID, Number.autoround(v.gainedPerSpent)))
end
end
 
return tostring(html)
return tostring(html)
end
end
Line 155: Line 191:
function p.getSCValue(frame)
function p.getSCValue(frame)
local args = frame:getParent().args
local args = frame:getParent().args
return p._getItemSellsFor(args[1], args[2], args.round)
return p._getItemSellsFor(args[1], 'melvorD:SlayerCoins', args[2], args.round)
end
end


function p._getSCValue(itemName, multiplier, rounding)
function p._getItemCurrencyValue(itemName, currencyID, multiplier, rounding)
local purchase = getPurchase(itemName)
local purchase = getPurchase(itemName)
if purchase == nil then
if purchase == nil then
return Shared.printError("No Slayer Shop item exists with the name: " .. itemName)
return Shared.printError("No Slayer Shop item exists with the name: " .. itemName)
end
end
 
local itemValue = getPurchaseValue(purchase)
local itemValue = getPurchaseValue(purchase, currencyID)
multiplier = tonumber(multiplier) or 1
multiplier = tonumber(multiplier) or 1
rounding = tonumber(rounding) or 0
rounding = tonumber(rounding) or 0
 
return Number.round2(itemValue * multiplier, rounding)
return Number.round2(itemValue * multiplier, rounding)
end
end