Module:Calculator/Summoning Interval Efficiency
From Melvor Idle
Documentation for this module may be created at Module:Calculator/Summoning Interval Efficiency/doc
local number = require('Module:Number')
local economy = require('Module:ItemEconomy')
local TimeSpan = require('Module:TimeSpan')
local p = {}
-- Calculates the time economy of using summoning synergies that decrease action interval
-- based on the player's stats.
local function calculateTimeEfficiency(playerStats)
local result = {
isInfinite = false,
twoTabletTimeSave = -1,
threeTabletTimeSave = -1,
effectiveTablets = -1
}
-- It is possible to get 100% tablet save chance. The rest of the calculation is irrelevant
-- since the amount of time saved is infinite.
if playerStats.tabletSaveChance >= 100 then
result.isInfinite = true
return result
end
-- Calculate item economy for tablet output
local eco = economy.ItemEconomy:new()
eco.outputsPerAction = playerStats.tabletsMade
eco.duplicationChance = playerStats.tabletDoubleChance
-- Values below are not included, but might be available as boosts.
eco.extraItemChance = 0
eco.extraItemAmount = 0
eco.flatExtraItems = 0
eco.extraBaseItemChance = 0
eco.extraBaseItems = 0
-- Calculate total amount of tablets made, including double chance
local averageTabletsMade = 1 * economy.estimatedOutputMultiplier(eco)
-- Calculate the effective amount of tablets the player has from one craft, including tablet save chance
local tabletSaveChance = number.clamp(playerStats.tabletSaveChance, 0, 99)
local effectiveTablets = averageTabletsMade / (1 - tabletSaveChance / 100)
-- The effective time per tablet.
-- two if the player was using tablets anyway
-- three if the player is using tablets specifically for the time save synergy
local twoTabletTime = (playerStats.actionTimeSaved / 2) * effectiveTablets
local threeTabletTime = (playerStats.actionTimeSaved / 3) * effectiveTablets
-- Subtract the total time saved by the time it takes to create the tablets.
local twoTabletTimeSave = twoTabletTime - playerStats.summoningInterval
local threeTabletTimeSave = threeTabletTime - playerStats.summoningInterval
result.effectiveTablets = effectiveTablets
result.twoTabletTimeSave = twoTabletTimeSave
result.threeTabletTimeSave = threeTabletTimeSave
return result
end
-- Adds a row to a table.
-- Optionally adds a suffix to the 'value' parameter.
local function addTableRow(tbl, header, value, suffix)
local row = tbl:tag("tr")
local headerCell = row:tag("th")
local valueCell = row:tag("td")
-- Check if the value is, or can be converted to a number.
local numValue = tonumber(value)
if suffix then
value = value .. suffix
end
-- If the numeric value is negative, colour the cell red.
if numValue and numValue < 0 then
valueCell = valueCell:css('color', 'red')
end
-- Fill cells with data.
headerCell:wikitext(header)
valueCell:wikitext(value)
return tbl
end
-- Format the calculated data and output a table.
local function createTable(calcResult)
local tableData = {
effectiveTablets,
twoTabletTimeSave,
threeTabletTimeSave
}
local tbl = mw.html.create("table")
:addClass("wikitable sticky-header text-align-right align-left-1")
if calcResult.isInfinite then
tableData.effectiveTablets = 'Infinite'
tableData.twoTabletTimeSave = 'Infinite'
tableData.threeTabletTimeSave = 'Infinite'
else
-- Calculate time saved in seconds for two and three tablet synergy
local twoTab = TimeSpan.fromSeconds(calcResult.twoTabletTimeSave)
local threeTab = TimeSpan.fromSeconds(calcResult.threeTabletTimeSave)
tableData.effectiveTablets = number.round(calcResult.effectiveTablets, 2)
tableData.twoTabletTimeSave = number.round(twoTab:getTotalSeconds(), 2)
tableData.threeTabletTimeSave = number.round(threeTab:getTotalSeconds(), 2)
end
addTableRow(tbl, "Effective tablets", tableData.effectiveTablets)
addTableRow(tbl, "Two tablet time save", tableData.twoTabletTimeSave, ' sec')
addTableRow(tbl, "Three tablet time save", tableData.threeTabletTimeSave, ' sec')
return tbl
end
function p.main(frame)
local args = frame:getParent().args
return p._main(args)
end
function p._main(args)
-- Parse inputs and turn intervals into integers (hundreds of a second)
local summoningInterval = number.toNumberOrError(args.summoningInterval)
local actionTimeSaved = number.toNumberOrError(args.actionTimeSaved)
local tabletsMade = number.toNumberOrError(args.tabletsMade)
local tabletDoubleChance = number.toNumberOrDefault(args.tabletDoubleChance, 0)
local tabletSaveChance = number.toNumberOrDefault(args.tabletSaveChance, 0)
local playerStats = {
summoningInterval = summoningInterval,
tabletsMade = tabletsMade,
tabletDoubleChance = tabletDoubleChance,
tabletSaveChance = tabletSaveChance,
actionTimeSaved = actionTimeSaved
}
local calcResult = calculateTimeEfficiency(playerStats)
local tbl = createTable(calcResult)
return tostring(tbl)
end
return p