FANDOM


-- <nowiki>
-- code for [[Template:Disassembly material calculator/t/sandbox]]
-- 	and [[Template:Disassembly material calculator/t2/sandbox]]
-- -> [[Calculator:Disassembly by material]]
local p = {}
 
local yesno = require('Module:Yesno')
local cats = mw.loadData('Module:Disassemble/data')
local materials = mw.loadData('Module:Disassemble/mats')
local exg = require('Module:ExchangeLite')
local coin = require('Module:Coins')._amount
local info = mw.loadData('Module:Disassembly category calculator/data') -- versioning info here
local chances = mw.loadData('Module:Disassembly material calculator/data') -- chance info here
local commas = require('Module:Addcommas')._add
local Title = mw.title.getCurrentTitle()
local spn = Title.subpageText
 
-- get the material name from a passed in string m
-- returns material name,true if successful
-- returns m (or the empty string), false if material not found
local function get_mat(m)
	local str = mw.text.trim(string.gsub(string.gsub(string.lower(m), ' parts?', ''), ' components?', ''))
 
	if materials[str] then
		return materials[str], true
	else
		return (m or ''), false
	end
end
local pagemat = get_mat(spn)
 
-- from a given category in the disassemble template, and a material, return the chance of that material
-- returns chance (as a decimal between 0 and 1) if successful
-- returns -1 if not
local function get_chance(c, m)
	-- strip off the excess stuff
	local m = mw.text.trim(string.gsub(string.gsub(string.lower(m), ' parts?', ''), ' components?', ''))
 
	local cat
	if type(c) == 'table' then
		cat = c
	else
		cat = cats[c]
	end
 
	local chs, ch
	if cat then
		chs = chances[cat.cat]
		if chs then
			ch = chs[m]
			if ch then
				return ch
			end
		end
	end
	return -1
end
 
local function gep(item)
	item = info.gemwnames[item] or info.names[item] or item
	local err, val = pcall(exg.load, {args={item, 'price'}})
	local err2, limit = pcall(exg.load, {args={item, 'limit'}})
	if err then
		if err2 then
			return val, limit
		else
			return val, 0
		end
	else
		return 0, -1
	end
end
 
local function img(item)
	return info.imgnames[item] or info.names[item] or item
end
 
local function junk(lv)
	local junkpast75 = {
		[75] = 4.2, [76] = 3.8, [77] = 3.4, [78] = 3.0, [79] = 2.7,
		[80] = 2.3, [81] = 2.0, [82] = 1.7, [83] = 1.4, [84] = 1.2,
		[85] = 1.0, [86] = 0.8, [87] = 0.6, [88] = 0.4, [89] = 0.3 }
 
	lv = tonumber(lv) or 1
	if lv >= 90 then
		return 0
	elseif lv >= 75 then
		return junkpast75[lv]
	else
		return 100 - 1.1 * lv
	end
end
 
local function plink(page, name, img)
	return string.format('[[File:%s.png|link=%s]] [[%s|%s]]', img, page, page, name)
end
 
local function coins(td, am)
	if am == 0 then
		td	:wikitext("''N/A''")
			:addClass('table-na')
	else
		td	:wikitext(coin(am, false))
 
	end
	td	:attr('data-sort-value', am)
end
 
 
local function round(n)
	-- significant figure funciton
	-- only applies to numbers < 1
	local function sigfig(n, f)
		f = math.floor(f)
		if n > 1 or f < 1 then
			return n
		end
		local prec = 0
		for i = 3, 10, 1 do
			if n * 10^i >= 1 then
				prec = i + f - 2
				break
			end
		end
 
		if prec == 0 then 
			return 0
		end
 
		return string.format('%.' .. prec .. 'f', n)
	end
	if n >= 10 then
		return string.format('%.1f', n)
	elseif n >= 0.1 then
		return string.format('%.2f', n)
	else
		return sigfig(n, 2)
	end
end
 
 
 
-- row creation for special materials
-- item | number per item | always? | junk | price each | buy limit | mat cost
local function make_row_special(data)
	local tr = mw.html.create('tr')
	local str
 
	data.cqty = data.sqty
 
	if data.iqty > 1 then
		str = string.format('%s %s %s', data.iqty, '×', plink(data.page, data.name, data.img))
	else
		str = plink(data.page, data.name, data.img)
	end
 
	local spcstring = '100%'
	local spcstringsort = 100
	local chance = 1
	if data.chance then
		chance = data.chance / 100
		spcstringsort = data.chance
		spcstring = data.chance .. '%'
	elseif not data.spchance then
		spcstring = '{{not okay}}'
		spcstringsort = 0
	end
	local val = data.price * data.iqty / (data.cqty * chance)
	if val < 100 then
		val = string.format("%.2f", val)
	else
		val = string.format("%.0f", val)
	end
	tr	:tag('td')
			:css('text-align','left')
			:wikitext(str)
			:attr('data-sort-value', data.name)
		:done()
		:tag('td')
			:wikitext(data.cqty)
			:attr('data-sort-value', data.cqty)
		:done()
		:tag('td')
			:wikitext(spcstring)
			:attr('data-sort-value', tostring(spcstringsort))
		:done()
		:tag('td')
			:wikitext(string.format('%.1f%%', data.junk))
			:attr('data-sort-value', data.junk)
		:done()
 
	coins(tr:tag('td'), data.price)
	if tonumber(data.limit) and data.limit > 0 then
		tr	:tag('td')
				:attr('data-sort-value', data.limit)
				:wikitext(commas(data.limit))
			:done()
	elseif tonumber(data.limit) and data.limit < 0 then
		tr	:tag('td')
				:attr('data-sort-value', 0)
				:wikitext("''N/A''")
				:addClass('table-na')
			:done()
	else
		tr	:tag('td')
				:attr('data-sort-value', 0)
				:wikitext("''Unknown''")
			:done()
	end
 
	coins(tr:tag('td'), val)
	return tostring(tr)
end
 
-- non-special mat row
-- item | cqty | junk | price each | buy limit | chance of mat per nonjunk | overall chance per item base/red5/red9 | cost base/red5/red9
local function make_row(data)
	if data.isspecial then
		return make_row_special(data)
	end
 
	local tr = mw.html.create('tr')
	local chance = {}
	local val = {}
 
	local str
 
	if data.iqty > 1 then
		str = string.format('%s %s %s', data.iqty, '×', plink(data.page, data.name, data.img))
	else
		str = plink(data.page, data.name, data.img)
	end
 
	chance.before = data.chance * 100
	chance.base = (1 - data.junk/100) * data.chance * data.cqty
 
	val.base = data.price * data.iqty / chance.base
 
	chance.base = round(chance.base * 100)
 
	val.matsperhour = 3000 * chance.base/100
 
 
	--round to 0dp if >100, else 2dp
	for i,v in pairs(val) do
		if v < 100 then
			val[i] = string.format("%.2f", v)
		else
			val[i] = string.format("%.0f", v)
		end
	end
 
	tr	:attr({
		['data-dis-mats'] = data.cqty,
		['data-dis-junk'] = data.junk,
		['data-dis-price'] = data.price,
		['data-dis-raw'] = chance.before,
		})
		:addClass('dis-calc-row')
		:tag('td')
			:css('text-align','left')
			:wikitext(str)
			:attr('data-sort-value', data.name)
		:done()
		:tag('td')
			:wikitext(data.cqty)
			:attr('data-sort-value', data.cqty)
		:done()
		:tag('td')
			:wikitext(string.format('%.1f%%', data.junk))
			:attr('data-sort-value', data.junk)
			:addClass('data-dis-junkcell')
		:done()
	coins(tr:tag('td'), data.price)
	if tonumber(data.limit) and data.limit > 0 then
		tr	:tag('td')
				:attr('data-sort-value', data.limit)
				:wikitext(commas(data.limit))
			:done()
	elseif tonumber(data.limit) and data.limit < 0 then
		tr	:tag('td')
				:attr('data-sort-value', 0)
				:wikitext("''N/A''")
				:addClass('table-na')
			:done()
	else
		tr	:tag('td')
				:attr('data-sort-value', 0)
				:wikitext("''Unknown''")
			:done()
	end
 
	tr	:tag('td')
			:attr('data-sort-value', chance.before)
			:wikitext(chance.before .. '%')
		:done()
 
	tr	:tag('td')
			:attr('data-sort-value', chance.base)
			:wikitext(chance.base .. '%')
			:addClass('data-dis-chancecell')
		:done()
 
	local costtd = tr:tag('td')
	costtd:addClass('data-dis-costcell')
	coins(costtd, val.base)
 
	tr	:tag('td')
			:attr('data-sort-value', val.matsperhour)
			:wikitext(commas(val.matsperhour))
			:addClass('data-dis-mphcell')
		:done()
 
 
	return tostring(tr)
 
end
 
-- special case: potions
-- cqty does not vary, it might actually idk
local function potion(data)
	local rows = {}
 
	if data.calcvalue and data.calccomp then
		data.name = string.format('%s (%s)', data.page, data.calccomp)
		data.img = img(data.name)
		data.cqty = data.calccomp
		data.price = data.calcvalue
		data.limit = -1
		return make_row(data)
	end
 
	-- setup 6-dose
	data.name = data.page .. ' (6)'
	data.img = img(data.name)
	data.cqty = 6
	data.price, data.limit = gep(data.name)
 
	if data.price > 0 then
		-- if 6-dose has a price, then this is a flask; only show 6 dose (5 and lower not GE-able)
		return make_row(data)
	else
		data.name = data.page .. ' (4)'
		data.price, data.limit = gep(data.name)
		if data.price > 0 then
		-- if 4 dose has a price, this is a 4-dose vial
			for i = 4, 1, -1 do
				data.name = string.format('%s (%s)',data.page,i)
				data.img = img(data.name)
				data.cqty = i
				data.price, data.limit = gep(data.name)
				table.insert(rows, make_row(data))
			end
		else
			-- if 4 dose does not have a price, this is a 2-dose mix
			for i = 2, 1, -1 do
				data.name = string.format('%s (%s)',data.page,i)
				data.img = img(data.name)
				data.cqty = i
				data.price, data.limit = gep(data.name)
				table.insert(rows, make_row(data))
			end
		end
		return table.concat(rows, '\n')
	end
end
 
-- main parsing function and module entry point
p._main = function (args)
	local cat = cats[string.lower(args.category)]
 
	if not cat then
		return ''
	end
 
	local data = {}
	local rows = {}
	local pot = args.potion or cat.potion or false
	pot = string.lower(tostring(pot))
	data.isspecial = args.isspecial
 
	-- if is special, get the number of special mat per item out of the template
	if data.isspecial then
		local _special = mw.text.split(args.special or '','%s*,%s*')
 
		local numsp = 1
		local chsp = nil
 
		local specmatcount = table.maxn(_special)
		for i, v in ipairs(_special) do
			v = string.lower(v)
				:gsub('components?','')
				:gsub('parts?','')
			local _m,_q,_c = v:match('(%w+)%s*%[?(%d*)%]?%s*%{?(%d*)%}?')
			local _name, matb = get_mat(_m)
			local _chance = nil
			local _quant = tonumber(_q) or 1
 
			if _c and _c ~= '' and tonumber(_c) then
				_chance = tonumber(_c)
			elseif yesno(args.specialchance) and specmatcount == 1 then
				_chance = 100
			end
 
 
			_name = mw.text.trim(_name)
			if v:find('%S') then
				if matb and _name == pagemat then
					numsp = _quant
					chsp = _chance
					break
				end
			end
		end
 
		if string.lower(args.specialchance or '') == 'no' then
			data.spchance = false
		else
			if args.specmatcount == 1 then
				data.spchance = true
			elseif args.allspecmats then
				data.spchance = true
			else
				data.spchance = false
			end
		end
		data.sqty = numsp
		data.cqty = numsp
		data.chance = chsp
	else
		data.chance = get_chance(cat, pagemat)
		if data.chance < 0 then
			return ''
		end
		data.cqty = tonumber(cat.compqty) or 1
	end
 
	data.iqty = tonumber(cat.itemqty) or 1
	data.page = args['%PAGE%']
	data.junk = junk(args.level)
 
	-- defaults
	data.name = data.page
	data.img = img(data.page)
	data.calcvalue = tonumber(args.calcvalue) or nil
	data.calccomp = tonumber(args.calccomp) or nil
 
	if yesno(pot) then
		return potion(data)
	end
 
	if info.versions[args['%PAGE%']] then
		for i,v in ipairs(info.versions[args['%PAGE%']]) do
			data.name = v
			if data.calcvalue then
				data.price, data.limit = data.calcvalue, -1
			else
				data.price, data.limit = gep(v)
			end
			data.img = img(v)
			table.insert(rows, make_row(data))
		end
		return table.concat(rows, '\n')
	else
		if data.calcvalue then
			data.price, data.limit = data.calcvalue, -1
		else
			data.price, data.limit = gep(data.page)
		end
		return make_row(data)
	end
end
 
 
-- special component entry point
p.special = function(frame)
	local args = frame:getParent().args
	args.isspecial = true
	return p._main(args)
end
 
-- normal component entry point
p.main = function(frame)
	local args = frame:getParent().args
	args.isspecial = false
	return p._main(args)
end
 
return p

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.