Module:SeedPackValue
Jump to navigation
Jump to search
Module documentation
This documentation is transcluded from Template:No documentation/doc. [edit] [history] [purge]
This module does not have any documentation. Please consider adding documentation at Module:SeedPackValue/doc. [edit]
Module:SeedPackValue's function main is invoked by Template:SeedPackTable.
Module:SeedPackValue's function main is invoked by Template:SeedPackValue.
Module:SeedPackValue requires Module:Addcommas.
Module:SeedPackValue requires Module:Average drop value.
Module:SeedPackValue requires Module:Coins.
Module:SeedPackValue requires Module:Paramtest.
Module:SeedPackValue requires Module:Yesno.
Module:SeedPackValue loads data from Module:GEPrices/data.json.
local p = {}
local ask = mw.smw.ask
local decode = mw.text.jsonDecode
local html = mw.html
local avgDropVal = require('Module:Average drop value').totalval
local coins = require('Module:Coins')._amount
local commas = require('Module:Addcommas')._add
local default = require('Module:Paramtest').default_to
local yesNo = require('Module:Yesno')
local prices = mw.loadJsonData('Module:GEPrices/data.json')
sortKey = {--[[allotment]] "Potato seed", "Onion seed", "Cabbage seed", "Tomato seed", "Sweetcorn seed", "Strawberry seed", "Watermelon seed", "Snape grass seed", --[[flower]] "Marigold seed", "Rosemary seed", "Nasturtium seed", "Woad seed", "Limpwurt seed", --[[herb]] "Guam seed", "Marrentill seed", "Tarromin seed", "Harralander seed", "Ranarr seed", "Toadflax seed", "Irit seed", "Avantoe seed", "Kwuarm seed", "Snapdragon seed", "Cadantine seed", "Lantadyme seed", "Dwarf weed seed", "Torstol seed", --[[hops]] "Barley seed", "Hammerstone seed", "Asgarnian seed", "Jute seed", "Yanillian seed", "Krandorian seed", "Wildblood seed", --[[bush]] "Redberry seed", "Cadavaberry seed", "Dwellberry seed", "Jangerberry seed", "Whiteberry seed", "Poison ivy seed", --[[tree]] "Acorn", "Willow seed", "Maple seed", "Yew seed", "Magic seed", --[[fruit tree]] "Apple tree seed", "Banana tree seed", "Orange tree seed", "Curry tree seed", "Pineapple seed", "Papaya tree seed", "Palm tree seed", "Dragonfruit tree seed", --[[cactus]] "Cactus seed", "Potato cactus seed", --[[hardwood]] "Teak seed", "Mahogany seed", --[[special single patches]] "Redwood tree seed", "Mushroom spore", "Belladonna seed", "Calquat tree seed", "Celastrus seed", "Hespori seed", "Spirit seed" }
-- Lows are calculated
local packTierRolls = {
{
total = 6,
medium = {
low = 1,
high = 3,
},
high = {
low = 0,
high = 0,
},
},
{
total = 7,
medium = {
low = 2,
high = 3,
},
high = (1/11),
},
{
total = 8,
medium = {
low = 2,
high = 4,
},
high = {
low = 0,
high = 1,
},
},
{
total = 9,
medium = {
low = 3,
high = 5,
},
high = {
low = 1,
high = 2,
},
},
{
total = 10,
medium = {
low = 4,
high = 6,
},
high = {
low = 1,
high = 3,
},
},
}
local taskDifficultyCount = {
easy = {
total = 31,
tiers = { 11, 12, 8, 0, 0 },
},
medium = {
total = 22,
tiers = { 0, 4, 10, 8, 0 },
},
hard = {
total = 18,
tiers = { 0, 0, 3, 8, 7 },
},
}
function averageRolls(high, low)
return high - ((high - low) / 2)
end
function avgTierRolls(num)
local tierRolls = packTierRolls[num]
local high = 0
if(type(tierRolls.high) == 'table') then
high = averageRolls(tierRolls.high.high, tierRolls.high.low)
else
high = tierRolls.high or 0
end
local medium = averageRolls(tierRolls.medium.high, tierRolls.medium.low) or 0
local low = (tierRolls.total - high - medium) or 0
return { low = low, medium = medium, high = high }
end
function difficultyRolls(type)
local low, medium, high = 0, 0, 0
local tierTaskTotal = taskDifficultyCount[type].total
local tiersTable = taskDifficultyCount[type].tiers
for tierNum, tierTaskCount in ipairs(tiersTable) do
local avgRollCount = avgTierRolls(tierNum)
high = high + ((tierTaskCount / tierTaskTotal) * avgRollCount.high)
medium = medium + ((tierTaskCount / tierTaskTotal) * avgRollCount.medium)
low = low + ((tierTaskCount / tierTaskTotal) * avgRollCount.low)
end
return { low = low, medium = medium, high = high }
end
function createRow(seedTable)
local priceText = nil
local profitText = nil
local cellClass = nil
local cellCss = nil
if(seedTable.price == nil) then
priceText = '<small>N/A</small>'
profitText = '<small>N/A</small>'
cellClass = 'table-na nohighlight'
cellCss = 'text-align:center'
else
priceText = coins(seedTable.price)
profitText = coins(seedTable.profit)
end
return html.create('tr')
:tag('td'):wikitext('[[File:' .. seedTable.name .. '_5.png|link=|' .. seedTable.name .. ']]'):done()
:tag('td'):wikitext('[[' .. seedTable.name .. ']]'):done()
:tag('td'):wikitext(priceText):addClass(cellClass):cssText(cellCss):done()
:tag('td'):wikitext(string.format("%.3f", seedTable.quantityOutput)):done()
:tag('td'):wikitext(profitText):addClass(cellClass):cssText(cellCss):done()
end
function createTable(ret, tier, difficulty, useSpiritSeed, useHesporiSeed)
local wikitable = html.create('table'):addClass('wikitable sortable align-center-1 align-center-2 align-center-3 align-center-4 align-center-5')
wikitable:tag('tr')
:tag('th'):wikitext('Seed'):attr('colspan', '2'):done()
:tag('th'):wikitext('Price'):done()
:tag('th'):wikitext('Quantity'):done()
:tag('th'):wikitext('Value'):done()
for _,v in ipairs(sortKey) do
wikitable:node(createRow(ret.seedsCalculated[v]))
end
ret['wikitable'] = tostring(wikitable) .. '\n\nThe average expected value of ' .. (tier and 'Tier ' .. tier or '') .. ' seed packs ' .. (difficulty and 'from ' .. difficulty .. ' Farming contracts' or '') .. ' is ' .. coins(string.format("%.2f", ret.totalProfit)) .. ' coins.'
if(tier == nil or tier > 1) then
ret.wikitable = ret.wikitable .. ((useSpiritSeed and ret.spiritSeedProfit > 0) and '\n\nTrading in spirits seeds for tier 5 seed packs increases the profit by '.. coins(string.format("%.2f", ret.spiritSeedProfit)) .. ' coins.' or '')
ret.wikitable = ret.wikitable .. ((useHesporiSeed and ret.hesporiSeedProfit > 0) and '\n\nPlanting hespori seeds and killing hespori increases the average profit by '.. coins(string.format("%.2f", ret.hesporiSeedProfit)) .. ' coins.' or '')
ret.wikitable = ret.wikitable .. ((useSpiritSeed or useHesporiSeed) and '\n\nThese increase the profit' .. ((useSpiritSeed and useHesporiSeed) and ' by ' .. coins(string.format("%.2f", ret.spiritSeedProfit + ret.hesporiSeedProfit)) or '') .. ' to ' .. coins(string.format("%.2f", ret.totalProfit + ret.spiritSeedProfit + ret.hesporiSeedProfit)) .. ' coins.' or '')
end
return ret.wikitable
end
function calc(tables, rolls)
local seedsCalculated = {}
local totalProfit = 0
local totalSpiritSeeds = 0
local totalHesporiSeeds = 0
for level, seedTable in pairs(tables) do
for _, drop in ipairs(seedTable) do
local item = drop['Dropped item']
seedsCalculated[item] = {}
seedsCalculated[item]['name'] = item
seedsCalculated[item]['price'] = prices[item]
local numer, divis = string.match(drop['Rarity'], '([%d%.]+)/([%d%.]+)')
if((numer ~= nil) and (divis ~= nil)) then
seedsCalculated[item]['rarityValue'] = numer/divis
else
seedsCalculated[item]['rarityValue'] = expr(rarity)
end
seedsCalculated[item]['quantityAvg'] = drop['Quantity High'] - ((drop['Quantity High'] - drop['Quantity Low']) / 2)
seedsCalculated[item]['quantityOutput'] = rolls[level] * seedsCalculated[item].quantityAvg * seedsCalculated[item].rarityValue
seedsCalculated[item]['profit'] = ((seedsCalculated[item].price ~= nil) and (seedsCalculated[item].quantityOutput * seedsCalculated[item].price) or 0)
seedsCalculated[item]['totalWithoutSpiritSeed'] = seedsCalculated[item].profit or 0
totalProfit = totalProfit + (seedsCalculated[item].profit or 0)
if(item == 'Spirit seed') then
totalSpiritSeeds = totalSpiritSeeds + seedsCalculated[item].quantityOutput
end
if(item == 'Hespori seed') then
totalHesporiSeeds = totalHesporiSeeds + seedsCalculated[item].quantityOutput
end
end
end
return {
seedsCalculated = seedsCalculated,
totalProfit = totalProfit,
totalSpiritSeeds = totalSpiritSeeds,
totalHesporiSeeds = totalHesporiSeeds,
}
end
function p.getSeedDropTables()
local query = {
"[[-Has subobject::Seed pack]]",
"?=#-",
"?Drop JSON#-",
limit = 500,
offset = 0,
}
local t1 = os.clock()
local smwData = ask(query)
local t2 = os.clock()
assert(smwData ~= nil and #smwData > 0, 'SMW query failed to find seed pack drops')
mw.log(string.format('SMW: entries %d, time elapsed: %.3f ms.', #smwData, (t2 - t1) * 1000))
local low, medium, high = {}, {}, {}
for _, drop in ipairs(smwData) do
local json = decode(drop["Drop JSON"])
local str = string.lower(json['Dropped from'])
if(str == 'seed pack#low seed') then
table.insert(low, json)
elseif(str == 'seed pack#medium seed') then
table.insert(medium, json)
elseif(str == 'seed pack#high seed') then
table.insert(high, json)
end
end
return { low = low, medium = medium, high = high }
end
function p._main(args, frameArgs)
local filter = string.lower(default(args[1], ''))
local tier = (packTierRolls[tonumber(filter:sub(-1))] and tonumber(filter:sub(-1)) or nil)
local difficulty = (taskDifficultyCount[filter] and filter or nil)
local useSpiritSeed = yesNo(default(args.spiritseed, false))
local displayTable = yesNo(default(args['table'] or frameArgs['table'], false))
local useHesporiSeed = yesNo(default(args.hespori, false))
local hesporiValue = (useHesporiSeed and avgDropVal('Hespori', nil, nil, nil, nil, nil, false) or 0)
local seedTables = p.getSeedDropTables()
local tier5Data = {}
if(useSpiritSeed) then
tier5Data = calc(seedTables, avgTierRolls(5))
tier5Data['spiritSeedProfit'] = 0
local spiritSeedPerPack = tier5Data.seedsCalculated['Spirit seed'].quantityOutput
local result = 1
while(result >= 1) do
result = spiritSeedPerPack * tier5Data.totalProfit
tier5Data['spiritSeedProfit'] = tier5Data.spiritSeedProfit + result
spiritSeedPerPack = spiritSeedPerPack * tier5Data.seedsCalculated['Spirit seed'].quantityOutput
end
-- This is effectively a short-circuit to avoid additional processing
if(tier == 5) then
tier5Data['hesporiSeedProfit'] = tier5Data.totalHesporiSeeds * hesporiValue
if(displayTable) then
return createTable(tier5Data, tier, difficulty, useSpiritSeed, useHesporiSeed)
else
return tier5Data.totalProfit + tier5Data.spiritSeedProfit + tier5Data.hesporiSeedProfit
end
end
end
local ret = {}
if(taskDifficultyCount[difficulty] ~= nil) then
ret = calc(seedTables, difficultyRolls(difficulty))
elseif(packTierRolls[tier] ~= nil) then
ret = calc(seedTables, avgTierRolls(tier))
end
ret['spiritSeedProfit'] = (useSpiritSeed and (ret.totalSpiritSeeds * (tier5Data.spiritSeedProfit + tier5Data.totalProfit)) or 0)
ret['hesporiSeedProfit'] = ret.totalHesporiSeeds * hesporiValue
if(displayTable) then
return createTable(ret, tier, difficulty, useSpiritSeed, useHesporiSeed)
else
return ret.totalProfit + ret.spiritSeedProfit + ret.hesporiSeedProfit
end
end
--[[ DEBUG
mw.log(p._main({'1',['spiritseed']='No',['Hespori']='Yes',['table']='Yes'}))
mw.log(p._main({'1',['spiritseed']='Yes',['Hespori']='No',['table']='No'}))
--]]
function p.main(frame)
local args = frame:getParent().args
local frameArgs = frame.args
--mw.logObject(args)
return p._main(args, frameArgs)
end
return p