Module:Get drop info

From RuneScape Classic Wiki
Jump to: navigation, search

Documentation for this module may be created at Module:Get drop info/doc

-- <nowiki>
local yesno = require('Module:Yesno')
local purge = require('Module:Purge')._purge
local params = require('Module:Paramtest')
local p = {}

--class, sort
local rarities = {
	always = { 'table-bg-blue', 1 },
	common = { 'table-bg-green', 2 },
	uncommon = { 'table-bg-yellow', 3 },
	rare = { 'table-bg-orange', 4 },
	['very rare'] = { 'table-bg-red', 5 },
	['extremely rare'] = { 'table-bg-purple', 5 },
	_default = { 'table-bg-grey', 6 }
}

local lang = mw.language.getContentLanguage()
local commas = function (n) return lang:formatNum(tonumber(n)) end

function expr(t)
	t = t:gsub(',', '')
	local err, val = pcall(mw.ext.ParserFunctions.expr, t)
	if err then
		return tonumber(val)
	else
		return false
	end
end

function sigfig(n, f)
	f = math.floor(f-1)
	if n == 0 then return 0 end
	local m = math.floor(math.log10(n))
	local v = n / (10^(m-f))
	v = math.floor(v) * 10^(m-f)
	return v
end

function p.main(frame)
	return p._main(frame:getParent().args)
end
function p.test(i)
	return p._main({item = i})
end
function p._main(args)
	local item = args.item or args[1]
	local skipheader = yesno(params.default_to(args.skipheader,'no'))
	local smwitem
	local propertyToQuery = 'Dropped item'
	if item then
		local cleanedName = item
		local dropVers = ''
		if item:match(' ?%(%d%)$') then
			cleanedName, dropVers = mw.ustring.match(item, '^(.-) ?(%(%d%))$')
		elseif item:match('%#') then
			cleanedName, dropVers = mw.ustring.match(item, '^(.-)%#([%w%s%(%)]+)$')
		end
		if dropVers ~= nil and dropVers ~= '' then
			smwitem = cleanedName .. '#' .. dropVers
		end
	else
		item = mw.title.getCurrentTitle().text
	end
	if not smwitem then
		smwitem = item
	end
	
	local q = {
		'[['..propertyToQuery..'::'..smwitem..']]',
		'?Dropped item text',
		'?Drop from#-',
		'?Loot from#-',
		'?Reward from#-',
		'?Drop Quantity',
		'?Rarity',
		'?Rarity Notes',
		limit = args.limit or 500,
		sort = args.sort,
		order = args.order
	}

	local smwdata = mw.smw.ask(q)
	if not smwdata then
		return ":''No drop sources found. To force an update, click "
				..purge('dml-'..mw.uri.anchorEncode(item), 'here', 'span')
				..".''[[Category:Empty drop lists]]"
	end
	
	local ret = {}
	if smwdata then
		for i,v in ipairs(smwdata) do
			for j,u in ipairs(makeLines(item, v) or {}) do
				table.insert(ret, u)
			end
		end
	end
	
	local t = mw.html.create('table')
	t	:addClass('wikitable sortable item-drops autosort=4,a')
		:css('text-align', 'center')
		:tag('tr')
			:tag('th'):wikitext('Source'):done()
			:tag('th'):wikitext('Level'):done()
			:tag('th'):wikitext('Quantity'):done()
			:tag('th'):wikitext('Rarity'):addClass('drops-rarity-header'):done()
	for i,v in ipairs(ret) do
		t:node(v)
	end
	
	if skipheader then
		return tostring(t)
	end
	
	return tostring(t)
end

function makeLines(item, data)
	-- iterate through different drop from parameters, get variant names
	local srcs = {drop=data['Drop from'],loot=data['Loot from'],reward=data['Reward from']}
	local srcsTable = {}
	for i,v in pairs(srcs) do
		if type(v) == 'string' then
			table.insert(srcsTable, {dtype=i,src=v})
		elseif type(v) == 'table' then
			for j,k in ipairs(v) do
				table.insert(srcsTable, {dtype=i,src=k})
			end
		end
	end

	-- iterate through found variants, get stats for each
	local srcsData = {}
	local _found = false
	for _,v in ipairs(srcsTable) do
		local qs = {'[['..v['src']..']]'}
		local level, levelsort
		local initfound = false
		if v['dtype'] == 'drop' then
			table.insert(qs, '?Combat level')
			table.insert(qs, '?All Combat level')
			local smwdata = mw.smw.ask(qs)
			smwdata = smwdata and smwdata[1]
			if smwdata then
				level = smwdata['Combat level'] or smwdata['All Combat level'] or 'Not Available'
				levelsort = smwdata['Combat level'] or smwdata['All Combat level'] or -1
				_found = true
				initfound = true
			end
		elseif v['dtype'] == 'loot' then
			table.insert(qs, '?Thieving level')
			table.insert(qs, '?All Thieving level')
			local smwdata = mw.smw.ask(qs)
			smwdata = smwdata[1]
			if smwdata then
				level = smwdata['Thieving level'] or smwdata['All Thieving level'] or 'Not Available'
				levelsort = smwdata['Thieving level'] or smwdata['All Thieving level'] or 99
				_found = true
				initfound = true
			end
		elseif v['dtype'] == 'reward' then
			local smwdata = mw.smw.ask(qs)
			smwdata = smwdata[1]
			if smwdata then
				level = 'N/A'
				levelsort = -1000
				_found = true
				initfound = true
			end
		end
		if initfound then
			if type(level) == 'table' then
				levelsort = level[1]
				level = table.concat(level, ', ')
			end
			if v['dtype'] == 'loot' then
				levelsort = 100 - levelsort
			end
			local cleanSrc = v['src']
			local splitSrc = mw.text.split(v['src'], '%#')
			if #splitSrc == 2 then
				splitSrc[2] = splitSrc[2]:gsub('_', ' ')
				cleanSrc = string.format('%s|%s <span class="beast-version">%s</span>', v['src'], splitSrc[1], splitSrc[2])
			end
			table.insert(srcsData, {src=cleanSrc,dtype=v['dtype'],lvl=level,lvlsort=levelsort,lvlimg=img})
		end
	end
	if not _found then
		return nil
	end

	local rows = {}
	-- iterate through found sources, create line for each
	for _, v in pairs(srcsData) do
		-- name,combat,dtype,quantity,rarity,raritynotes,members, membersnotes
		local dropline = line({v['src'], v['lvl'], v['lvlsort'], data['Drop Quantity'], data['Rarity'], data['Rarity Notes']})
		table.insert(rows, dropline)
	end

	return rows
end

function line(...)
	local name,
		combat,dtype,
		quantity,
		rarity,raritynotes = unpack(...)
	
	-- missing notes to empty string (and not nil)
	raritynotes = raritynotes or ''
	
	local rare_class, rare_sort = unpack(rarities._default)
	for key, value in pairs(rarities) do
		-- startswith
		if rarity:lower():sub(1, #key) == key then
			rare_class, rare_sort = unpack(value)
		end
	end
	
	-- Clean up the lists
	local qtysort = mw.text.split(quantity, '%D')[1]
	if qtysort == '' then
		qtysort = 0
	end
	local cmbclass = ''
	local cmbsort = combat
	if combat == 'N/A' then
		cmbclass = 'table-na'
		cmbsort = 0
	else
		combat, cmbsort = cmb(combat)
	end

	-- set row class and level sort by drop type
	if type(dtype) == 'string' then
		if dtype == 'thieving' then
			trclass = 'drop-thieving'
		elseif dtype == 'reward' then
			trclass = 'drop-reward'
		else
			trclass = 'drop-combat'
		end
	else
		trclass = 'drop-combat'
	end

	-- Check if name is already formated
	if name:match('^%[%[') then
		name = name
	else
		name = '[['..name..']]'
	end
	-- Table row creation
	local ret = mw.html.create('tr')
	ret		:css('text-align','center')
			:addClass(trclass)
			:tag('td')
				:css('text-align','left')
				:wikitext(name)
			:done()
			:tag('td')
				:wikitext(combat)
				:addClass(cmbclass)
				:attr('data-sort-value', cmbsort)
			:done()
			:tag('td')
				:attr('data-sort-value', qtysort)
				:wikitext(quantity)
			:done()
	local rarity_cell = ret:tag('td')
	local rarity_span = rarity_cell:tag('span')
	rarity_span:wikitext(rarity)
	rarity_cell:attr('data-sort-value', rare_sort)
		:addClass(rare_class)
	:done()
	
	if #raritynotes > 5 then
		rarity_cell:wikitext(raritynotes)
	end
	return ret:done()
end

function cmb(levels)
	-- if no level is given, return unknown
	if not levels then
		return 'Unknown', 0
	end

	-- split list into table
	-- recreate the list string to ensure consistent formatting
	local numstr = {}
	for v in mw.text.gsplit(levels, '[,;]') do
		v = mw.text.trim(v)
		table.insert(numstr,tonumber(v))
	end

	table.sort(numstr)
	
	-- give a range if 5+ combat levels
	if #numstr > 4 then
		return numstr[1] .. '–' .. numstr[#numstr], numstr[1]
	end
	-- To prevent any possible confusion with formatted numbers
	-- elements should be separated with semicolons followed by a space
	return table.concat(numstr,'; '), numstr[1] or 0
end

return p
-- </nowiki>