Module:Fishing chance calculator

From WIDEVERSE Wiki
Revision as of 18:26, 9 August 2021 by en>Gaz Lloyd
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Documentation for this module may be created at Module:Fishing chance calculator/doc

local data = mw.loadData('Module:Fishing chance calculator/data')
local geprices = mw.loadData('Module:GEPrices/data')
local yn = require('Module:Yesno')
local pt = require('Module:Paramtest')
local p = {}
local lang = mw.getContentLanguage()

function plink(link, image, text)
	if text == nil then
		text = link
	end
	if image == nil then
		image = link
	end
	return string.format('[[File:%s.png|link=%s]] [[%s|%s]]', image, link, link, text)
end
function plinkT(x)
	return plink(x.link, x.image, x.text)
end

function jagexInterpolation(hi, lo, lvl)
	return math.floor( ( (99-lvl)*lo + (lvl-1)*hi ) / 98 )
end

function multifloor(x, m)
	local _x = x
	for i,v in ipairs(m) do
		_x = math.floor( _x * v )
	end
	return _x
end

function gep(x)
	return geprices[x] or 0
end

function fnum(num, dp)
	local ret = math.pow(10, dp) * num + 0.5
	ret = math.floor(ret)
	ret = math.pow(10, -dp) * ret
	return lang:formatNum(ret)
end
function perc(x)
	return fnum(x*100,1)..'%'
end

function p.makeSimpleTable()
	local t = mw.html.create('table')
	t:addClass('wikitable sortable mw-collapsible mw-collapsed align-center-1 align-center-3 align-center-4 align-right-6 align-right-7')
		:tag('caption'):wikitext('Fish high- and lowchances'):done()
		:tag('tr')
			:tag('th'):wikitext('Order'):done()
			:tag('th'):wikitext('Fish'):done()
			:tag('th'):wikitext('Level'):done()
			:tag('th'):wikitext('Base XP'):done()
			:tag('th'):wikitext('Fishing spot'):done()
			:tag('th'):wikitext('Lowchance'):done()
			:tag('th'):wikitext('Highchance'):done()
	for i,v in ipairs(data) do
		t:newline()
		t:tag('tr')
			:tag('td')
				:wikitext(i)
			:done()
			:tag('td')
				:wikitext(plinkT(v))
			:done()
			:tag('td')
				:wikitext(v.level)
			:done()
			:tag('td')
				:wikitext(v.xp)
			:done()
			:tag('td')
				:wikitext(lang:ucfirst(v.spot or v.text))
			:done()
			:tag('td')
				:wikitext(v.low)
			:done()
			:tag('td')
				:wikitext(v.high)
			:done()
	end
	t:newline()
	return t
end


function p.calculator(frame)
	return p._calculator(frame:getParent().args)
end
function p.calculator_notemplate(frame)
	return p._calculator(frame.args)
end

local multipliers_list = {
	skillchompa = {
		cobalt = 1.01,
		viridian = 1.02,
		azure = 1.03,
		crimson = 1.04,
		crystal = 1.05
	},
	aura = {
		basic = 1.03,
		greater = 1.05,
		master = 1.07,
		supreme = 1.1,
		legendary = 1.15
	},
	outfit = {
		shark = 1.05,
		['fury shark'] = 1.07
	},
	rod = {
		['crystal rod'] = 1.05,
		["tavia's rod"] = 1.1,
		["tavia's rod"] = 1.1
	},
	ring = 1.03,
	dsf = 1.1,
	juju = 1.05,
	menaphos = 1.1,
	familiar = {
		['granite crab'] = 1,
		['ibis'] = 3,
		['granite lobster'] = 4
	}
	
}

function p._calculator(args)
	local level = tonumber(args.level) or 99
	local spots = {}
	local spots_order = {}
	
	-- setup multipliers
	local hi_multipliers = {}
	local lo_multipliers = {}
	
	local xp_multipliers = {}
	
	-- if table.insert(t, nil) is a noop
	for i,v in ipairs({ 'rod', 'skillchompa', 'outfit', 'aura' }) do
		if pt.has_content(args[v]) then
			table.insert(hi_multipliers, multipliers_list[v][string.lower(args[v])])
		end
	end
	for i,v in ipairs({'ring', 'juju', 'dsf'}) do
		if yn(args[v]) then
			table.insert(hi_multipliers, multipliers_list[v])
		end
	end
	
	-- only applies to menaphos fish
	local menaphos = {}
	if yn(args.menaphos) then
		menaphos = { multipliers_list.menaphos }
	end
	
	-- both hi and low
	local _h = tonumber(args.honed) or 0
	local honed = 0
	if _h > 0 then
		honed = 1 + 0.02 * _h
	end
	
	-- familiar is special
	local familiar = 0
	if pt.has_content(args.familiar) then
		familiar = multipliers_list.familiar[string.lower(args.familiar)] or 0
	end
	
	local is_gws_toggled = yn(args.gws_toggle)
	
	--[==[
	-- undecided if i want to add this, since i then should really add all of the other xp multipliers and there's a lot
	if (tonumber(args.xpoutfit) or 0) > 0 then
		if tonumber(args.xpoutfit) >= 4 then
			table.insert(xp_multipliers, 1.05)
		else
			table.insert(xp_multipliers, 1+(0.01*tonumber(args.xpoutfit)))
		end
	end
	--]==]
	
	
	-- filter into spot-groupings of the relevant things based on level
	for i,v in ipairs(data) do
		local addSpot = level >= v.level
		if v.is_gws_toggle then
			addSpot = addSpot and is_gws_toggled
		end
		if addSpot then
			local spotName = v.spot or v.name
			if spots[spotName] == nil then
				spots[spotName] = { v }
				table.insert(spots_order, spotName)
			else
				table.insert(spots[spotName], v)
			end
		end
	end
	
	-- construct output table
	local ret = mw.html.create('table')
	ret:addClass('wikitable sortable sticky-header align-right-3 align-right-4 align-right-5 align-right-6 align-right-7')
		:tag('tr')
			:tag('th'):wikitext('Spot'):done()
			:tag('th'):wikitext('Available fish'):done()
			:tag('th'):wikitext('Fish XP'):done()
			:tag('th'):wikitext('Fish chance'):done()
			:tag('th'):wikitext('Fish/hr'):done()
			:tag('th'):wikitext('Overall XP/hr'):done()
			:tag('th'):wikitext('Overall GP/hr'):done()
	ret:newline()
	
	for i,v in ipairs(spots_order) do
		local tr = ret:tag('tr')
		tr:tag('td'):wikitext(lang:ucfirst(v))
		local info = { links={}, xps={}, rawchance={}, actualchance={}, fchance = {}, fph = {} }
		local rollingChance = 0
		local delay = spots[v][1].delay or 4
		local totalGPH = 0
		local totalXPH = 0
		for j,u in ipairs(spots[v]) do
			table.insert(info.links, plinkT(u))
			table.insert(info.xps, u.xp)
			local newHi = multifloor(u.high, hi_multipliers)
			if u.is_menaphos then
				newHi = multifloor(newHi, menaphos)
			end
			local newLo = multifloor(u.low, lo_multipliers)
			if honed > 0 then
				newHi = math.ceil( newHi * honed )
				newLo = math.ceil( newLo * honed )
			end
			if familiar > 0 then
				local fambuff = math.floor( familiar * math.floor(10*(u.high-u.low)/98) /10 )
				newHi = newHi + fambuff
				newLo = newLo + fambuff
			end
			
			
			local rawchance = jagexInterpolation(newHi, newLo, level)
			table.insert(info.rawchance, rawchance)
			local newRollingChance = (1-rollingChance) *math.max(math.min(rawchance/256, 1), 0)
			table.insert(info.actualchance, newRollingChance)
			table.insert(info.fchance, perc(newRollingChance))
			local fph = 3600/(u.delay or 4) * newRollingChance
			table.insert(info.fph, fnum(fph, 0))
			totalGPH = totalGPH + fph * gep(u.ge or u.link)
			totalXPH = totalXPH + fph * u.xp
			rollingChance = rollingChance + newRollingChance
		end
		if (1-rollingChance) > 0 then
			table.insert(info.links, "''Nothing''")
			table.insert(info.xps, "''0''")
			table.insert(info.rawchance, 255)
			table.insert(info.actualchance, string.format("''%s''", 1-rollingChance))
			table.insert(info.fchance, string.format("''%s''", perc(1-rollingChance)))
			table.insert(info.fph, string.format("''%s''", fnum(3600/(delay or 4) * (1-rollingChance), 0)))
		end
		
		
		tr:tag('td'):wikitext(table.concat(info.links, '<br>')):done()
			:tag('td'):wikitext(table.concat(info.xps, '<br>')):done()
			:tag('td'):wikitext(table.concat(info.fchance, '<br>')):done()
			:tag('td'):wikitext(table.concat(info.fph, '<br>')):done()
			:tag('td'):wikitext(fnum(totalXPH, 1)):done()
			:tag('td'):wikitext(fnum(totalGPH, 0)):done()
		ret:newline()
		
		mw.logObject(info)
	end
	
	return ret
end


return p