Module:Calculator/Summoning Interval Efficiency: Difference between revisions

From Melvor Idle
(Create module to calculate time efficiency when using summoning synergies that decrease action interval)
 
mNo edit summary
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
local number = require('Module:Number')
local number = require('Module:Number')
local economy = require('Module:ItemEconomy')
local economy = require('Module:ItemEconomy')
local TimeSpan = require('Module:TimeSpan')


local p = {}
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 function calculateTimeEfficiency(playerStats)
local result = {
local result = {
Line 18: Line 21:
return result
return result
end
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
-- Calculate total amount of tablets made, including double chance
local averageTabletsMade = economy.estimatedOutput(
local averageTabletsMade = 1 * economy.estimatedOutputMultiplier(eco)
playerStats.tabletsMade,
0,
playerStats.tabletDoubleChance)


-- Calculate the effective amount of tablets the player has from one craft, including tablet save chance
-- Calculate the effective amount of tablets the player has from one craft, including tablet save chance
Line 45: Line 56:
end
end


-- Add a row to the table
-- Adds a row to a table.
-- If the value parameter is a negative number, colour the cell red.
-- Optionally adds a suffix to the 'value' parameter.
local function addTableRow(tbl, header, value)
local function addTableRow(tbl, header, value, suffix)
     local row = tbl:tag("tr")
     local row = tbl:tag("tr")
     local cell = row:tag("td")
     local headerCell = row:tag("th")
      
     local valueCell = row:tag("td")
    row:tag("th"):wikitext(header)
 
-- Check if the value is, or can be converted to a number.
local numValue = tonumber(value)


    if type(value) == "number" and value < 0 then
if suffix then
         cell:css('color', 'red'):wikitext(value)
value = value .. suffix
    else
end
        cell:wikitext(value)
-- If the numeric value is negative, colour the cell red.
    if numValue and numValue < 0 then
         valueCell = valueCell:css('color', 'red')
     end
     end
   
    -- Fill cells with data.
    headerCell:wikitext(header)
    valueCell:wikitext(value)
   
     return tbl
     return tbl
end
end


-- Format the calculated data and output a table.
local function createTable(calcResult)
local function createTable(calcResult)
local tableData = {
local tableData = {
Line 71: Line 93:
         :addClass("wikitable sticky-header text-align-right align-left-1")
         :addClass("wikitable sticky-header text-align-right align-left-1")


if res.isInfinite then
if calcResult.isInfinite then
tableData.effectiveTablets = 'Infinite'
tableData.effectiveTablets = 'Infinite'
tableData.twoTabletTimeSave = 'Infinite'
tableData.twoTabletTimeSave = 'Infinite'
Line 77: Line 99:
else
else
-- Calculate time saved in seconds for two and three tablet synergy
-- Calculate time saved in seconds for two and three tablet synergy
local twoTab = number.actionTimeToTimeSpan(res.twoTabletTimeSave)
local twoTab = TimeSpan.fromSeconds(calcResult.twoTabletTimeSave)
     local threeTab = number.actionTimeToTimeSpan(res.threeTabletTimeSave)
     local threeTab = TimeSpan.fromSeconds(calcResult.threeTabletTimeSave)
     tableData.effectiveTablets = calcResult.effectiveTablets
     tableData.effectiveTablets = number.round(calcResult.effectiveTablets, 2)
tableData.twoTabletTimeSave = twoTab.totalSeconds
tableData.twoTabletTimeSave = number.round(twoTab:getTotalSeconds(), 2)
tableData.threeTabletTimeSave = threeTab.totalSeconds
tableData.threeTabletTimeSave = number.round(threeTab:getTotalSeconds(), 2)
end
end


addTableRow(tbl, "Effective tablets", tableData.effectiveTablets)
addTableRow(tbl, "Effective tablets", tableData.effectiveTablets)
addTableRow(tbl, "Two tablet time save", tableData.twoTabletTimeSave)
addTableRow(tbl, "Two tablet time save", tableData.twoTabletTimeSave, ' sec')
addTableRow(tbl, "Three tablet time save", tableData.threeTabletTimeSave)
addTableRow(tbl, "Three tablet time save", tableData.threeTabletTimeSave, ' sec')
return tbl
return tbl
end
end
Line 97: Line 119:
function p._main(args)
function p._main(args)
-- Parse inputs and turn intervals into integers (hundreds of a second)
-- Parse inputs and turn intervals into integers (hundreds of a second)
local summoningInterval = number.toNumberOrError(args.summoningInterval) * 100
local summoningInterval = number.toNumberOrError(args.summoningInterval)
local actionTimeSaved = number.toNumberOrError(args.actionTimeSaved) * 100
local actionTimeSaved = number.toNumberOrError(args.actionTimeSaved)
local tabletsMade = number.toNumberOrError(args.tabletsMade)
local tabletsMade = number.toNumberOrError(args.tabletsMade)
local tabletDoubleChance = number.toNumberOrDefault(args.tabletDoubleChance, 0)
local tabletDoubleChance = number.toNumberOrDefault(args.tabletDoubleChance, 0)

Latest revision as of 21:19, 13 April 2024

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