Module:Sandbox/User:Microbrews/Skilling success chart

From RuneRealm Wiki
Jump to navigation Jump to search
Module documentation
This documentation is transcluded from Template:Module sandbox/doc. [edit] [history] [purge]
Module:Sandbox/User:Microbrews/Skilling success chart requires Module:Chart data.

This module is a sandbox for Microbrews. It can be used to test changes to existing modules, prototype new modules, or just experimenting with lua features.

Invocations of this sandbox should be kept in userspace; if the module is intended for use in other namespaces, it should be moved out of the sandbox into a normal module and template.

This default documentation can be overridden by creating the /doc subpage of this module, as normal.

local chart = require( 'Module:Chart data' )

local p = {}

function interp(low, high, level)
	local value = math.floor(low*(99-level)/98 + high*(level-1)/98 + 0.5) + 1
	return math.min(math.max(value / 256, 0), 1)	
end

function oldInterp(low, high, level)
	local value = math.modf(low*(99-level)/98) + math.modf(high*(level-1)/98) + 1
	return math.min(math.max(value / 256, 0), 1)	
end

function bonusInterp(low, high, bonuslow, bonushigh, level)
	local value = interp(low, high, level)
	return value + (1-value)*interp(bonuslow, bonushigh, level)
end

function exponentInterp(low, high, exponent, level)
	return interp(low, high, level) ^ exponent
end

function cascadeInterp(bounds, level, index)
	local rate = 1.0
	for i, v in ipairs(bounds) do
		local low = (level >= v.altreq) and v.altlow or v.low
		local high = (level >= v.altreq) and v.althigh or v.high
		if i == index then
			rate = rate * interp(low, high, level)
			return rate
		end
		if level >= v.req then
			rate = rate * (1 - interp(low, high, level))
		end
	end
end

function birdhouseInterp(high, level)
	local level = math.max(50, level)
	local value = math.modf(high*(level-1)/98)
	return value / 1000
end

function ctsYield(low, high, level, lives)
	return lives / (1-interp(low, high, level))
end

function scriptInterp(low, high, level)
	local value = math.modf(low*(99-level)/98 + high*(level-1)/98)
	return math.min(math.max(value / 256, 0), 1)	
end

function caviarInterp(level, denom)
	return math.min(level, denom) / denom
end

function p._calculateDataSets(args)
	local dataSets = {}
	local inputs = {}
	local i = 1
	while args['label' .. i] do
		table.insert(inputs, {
			label = args['label' .. i],
			low = args['low' .. i] or 0,
			high = args['high' .. i],
			bonuslow = args['bonuslow' .. i] or nil,
			bonushigh = args['bonushigh' .. i] or nil,
			altlow = args['altlow' .. i] or args['low' .. i] or 0,
			althigh = args['althigh' .. i] or args['high' .. i],
			altreq = tonumber(args['altreq' .. i] or math.huge),
			denom = args['denom' .. i],
			req = tonumber(args['req' .. i] or 1),
			image = args['image' .. i] or 'hi',
			color = args['color' .. i] or '',
			exponent = args['exponent' .. i] or 1,
			lives = args['lives' .. i] or 0
		})
		i = i + 1
	end

	args.lowLevel = tonumber(args.lowLevel or 1)
	args.highLevel = tonumber(args.highLevel or 99)

	for i, input in ipairs(inputs) do
		local cutoffLevel = nil
		local data = {}
		for x = 1, input.req do
			local y
			if args.cascade then
				y = cascadeInterp(inputs, x, i)
			elseif args.birdhouse then
				y = birdhouseInterp(input.high, x)
			elseif (input.lives ~= 0) then
				y = ctsYield(input.low, input.high, x, input.lives)
			elseif args.script then
				y = scriptInterp(input.low, input.high, x)
			elseif args.caviar then
				y = caviarInterp(x, input.denom)
			elseif (input.exponent ~= 1) then
				y = exponentInterp(input.low, input.high, input.exponent, x)
			elseif input.bonuslow then
				y = bonusInterp(input.low, input.high, input.bonuslow, input.bonushigh, x)
			else
				y = interp(input.low, input.high, x)
			end
			if args.showbefore ~= 'no' or input.req == x or (y >= 0.999 and input.lives == 0) then
				table.insert(data, {x=x, y=y})
			end
			if y >= 0.999 and input.lives == 0  then
				cutoffLevel = x
				break
			end
		end

		table.insert(dataSets, {
	        data = data,
	        label = input.label .. "  ",
	        borderDash = {5, 5},
	        borderCapStyle = 'round',
	        pointRadius = 0,
	        baseColor = input.color,
	        pointStyleImg = input.image,
	    })

	    data = {}
		for x = input.req, args.highLevel do
			if cutoffLevel ~= nil then
				break
			end
			local y
			if args.cascade then
				y = cascadeInterp(inputs, x, i)
			elseif args.birdhouse then
				y = birdhouseInterp(input.high, x)
			elseif (input.lives ~= 0) then
				y = ctsYield(input.low, input.high, x, input.lives)
			elseif args.script then
				y = scriptInterp(input.low, input.high, x)
			elseif args.caviar then
				y = caviarInterp(x, input.denom)
			elseif (input.exponent ~= 1) then
				y = exponentInterp(input.low, input.high, input.exponent, x)
			elseif input.bonuslow then
				y = bonusInterp(input.low, input.high, input.bonuslow, input.bonushigh, x)
			else
				y = interp(input.low, input.high, x)
			end
			if y >= 0.999 and cutoffLevel == nil and input.lives == 0 then
				cutoffLevel = x
			end
			table.insert(data, {x=x, y=y})
		end

		table.insert(dataSets, {
	        data = data,
	        label = input.label .. "  ",
	        borderDash = {},
	        borderCapStyle = 'round',
	        baseColor = input.color,
	        pointRadius = 0,
	    })

	    if cutoffLevel ~= nil then
	    	table.insert(dataSets, {
		        data = {{x = cutoffLevel, y = 1}},
		        borderDash = {},
		        borderCapStyle = 'round',
		        baseColor = input.color,
		        pointRadius = 5,
	    	})
	    else
			table.insert(dataSets, {})
	    end
	end

	return dataSets
end

function p.main(frame)
	local args = frame:getParent().args
	
	return p._main(args)
end

function p._main(args)

    local plot = chart.newChart{ type = 'scatter' }
        :setTitle( args.label )
        :setDimensions( '540px', '400px', '540px', '400px', true )
        :setXLabel( args.xlabel or 'Level' )
        :setYLabel( args.ylabel or 'Success rate' )
        :setXLimits( nil, nil, 1 )
        :setDatasetsPerGroup(3)
        
    if args.lives1 == nil then
    	plot:setYFormat( 'percent' )
        :setYLimits( nil, nil, 0.1 )
        :setTooltipFormat( 'skillingSuccess' )
    else
    	plot:setYLimits( 0, nil, (tonumber(args.ystep) or 5))
        :setTooltipFormat( 'harvestLives' )
    end
    
	local dataSets = p._calculateDataSets(args)
	for i, dataSet in ipairs(dataSets) do
		plot:newDataSet(dataSet)
	end

    return plot
end

return p