Module:Sandbox/User:Betsan/foo

From the RuneScape Wiki, the wiki for all things RuneScape
Jump to: navigation, search
Module documentation
This documentation is transcluded from Template:Module sandbox/doc. [edit] [history] [purge]
Module:Sandbox/User:Betsan/foo requires Module:Coins image.
Module:Sandbox/User:Betsan/foo requires Module:Exchange.
Module:Sandbox/User:Betsan/foo requires Module:Paramtest.

This module is a sandbox for Betsan. 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.

-- <pre>
local p = {}

local params = require('Module:Paramtest')
local lang = mw.language.getContentLanguage()
local commas = function (n) return lang:formatNum(n) end
local coins_image = require('Module:Coins image')
local geprice = require('Module:Exchange')._price

local ns = mw.title.getCurrentTitle().nsText

local _noted = '&nbsp;<span style="color:#898989;">(noted)</span>'

--bg, txt, sort
local rarities = {
	always = { 'rarity-always', 1 },
	common = { 'rarity-common', 2 },
	uncommon = { 'rarity-uncommon', 3 },
	rare = { 'rarity-rare', 4 },
	['very rare'] = { 'rarity-very-rare', 5 },
	random = { 'rarity-random', 6 },
	varies = { 'rarity-random', 6 }
}

-- list of items to automatically not use gemw
-- this should only be used for items dropped by many monsters
local nogemw = {
	'clue scroll', 'starved ancient effigy', 'rare drop table', 'warpriest', 'court summons'
}

function p.main(frame)
	local args = frame.args
	-- Params and defaults
	local name,namenotes,
		quantity,quantitynotes,
		rarity,raritynotes = params.defaults{
					{args.Name,'Item'},
					{args.Namenotes,''},
					{args.Quantity,'unknown'},
					{args.Quantitynotes,''},
					{args.Rarity,'unknown'},
					{args.Raritynotes,''}
				}
	local jarname = params.default_to(args.JarName,"Earth Impling jar")
	
	local jarprice = 0
	local unusedabc
	
	unusedabc,jarprice = pcall(geprice,jarname)

	jarprice = tonumber(jarprice,10) or false
	
	local isCoins = name:lower() == 'coins'
	local altname = params.default_to(args.Alt,name)
	local gemwname = params.default_to(args.gemwname,name)
	local raritynotes = args.Raritynotes or ''
	rarity = params.ucflc(rarity)
	quantity = quantity:lower()
	local gemw = string.lower(args.gemw or 'yes') == 'yes'

	-- automatic no gemw
	for _, v in ipairs(nogemw) do
		if string.match(string.lower(name or ''), v) then
			gemw = false
			break
		end
	end

	local price
	local alt = false
	-- Test for existence of an exchange page
	local hasgemw
	if gemw and not isCoins then
		hasgemw, price = pcall(geprice,gemwname)
	elseif args.AltValue and not isCoins then
		price = args.AltValue:gsub(',','')
		alt = true
	elseif isCoins then
		price = 1
		alt = true
		gemw = false
	end
	-- Clean up price
	price = tonumber(price,10) or false
	
	_quantity = tonumber(string.match(quantity, "(%d+)"), 10)
	
	local profit 
	if price ~= false then
		profit = (price * _quantity) - jarprice
	else
		profit = '-'
	end
	
	-- Use 'File:<name>.png' if no image param
	-- Use 'File:<image>' if image param; image param will include extension
	-- Special catch for coins
	local image,image_n
	if isCoins then
		image_n = coins_image(quantity)
	else
		image_n = params.default_to(args.Image, name .. '.png')
	end
	if image_n:lower() == 'no' or params.is_empty(args.Name) then
		image = ''
	else
		image = '[[File:' .. image_n .. '|link=' .. name .. ']]'
	end
	-- this only affects the JSON
	local smwjson = string.lower(args.smwjson or '')
	if smwjson == 'no' then
		smwjson = false
	elseif smwjson == 'rdt' then
		smwjson = 'rdt'
	else
		smwjson = true
	end
		
	-- Table row
	local ret =  p._main{ name,
			altname,
			namenotes,
			quantity,
			quantitynotes,
			rarity,
			raritynotes,
			price,
			profit,
			alt,
			image,
			gemw,
			hasgemw,
			smwjson }

	-- categories for mainspace
	local cats = ''
	
	if ns == '' then
		cats = categories{name,quantity,rarity}
	end
	return ret..cats
end

function p._main(...)
	local name,altname,namenotes,
		quantity,quantitynotes,
		rarity,raritynotes,
		price,profit,alt,image,gemw,hasgemw,smwjson = unpack(...)
	local rare_class, rare_sort = unpack(rarities[rarity:lower()] or { 'rarity-unknown', 8 })
	local total, vsort, _h, _l
	quantity, total, vsort, _h, _l = qty(price,quantity)

	if type(vsort) ~= 'number' then
		vsort = 0
	end

	local _r = rarity

	if #quantitynotes > 3 then
		quantity = quantity..quantitynotes
	end

	if #raritynotes > 3 then
		rarity = rarity..raritynotes
	end

	-- Table row creation
	local ret = mw.html.create('tr')
			:css('text-align','center')
			:tag('td')
				:wikitext(image)
			:done()
			:tag('td')
				:css('text-align','left')
				:attr('data-sort-value',namesort(name,rare_sort))
				:wikitext(string.format('[[%s|%s]]%s',name,altname, #namenotes > 3 and namenotes or '' ))
			:done()
			:tag('td')
				:wikitext(quantity)
			:done()
			:tag('td')
				:attr('data-sort-value',rare_sort)
				:addClass(rare_class)
				:wikitext(rarity)
			:done()

	if gemw and hasgemw and not alt then
		local _coins = ' coin'..(price > 1 and 's' or '')

		ret	:tag('td')
				:attr('title',commas(price).._coins..' each')
				:attr('data-sort-value',vsort)
				:css({ ['text-align'] = 'right',
					cursor = 'help' })
				:wikitext(total)
			:done()
	elseif gemw and not hasgemw then
		ret	:tag('td')
				:attr('data-sort-value',vsort)
				:css({ ['text-align'] = 'right',
					cursor = 'help' })
				:tag('span')
					:attr('title','Exchange page not found for "'..name..'". Double check that the exact item name and casing is used for the "name" parameter. Add "gemw=no" to this template if this item cannot be traded on the Grand Exchange or ignore this error and wait for the exchange page to be made.')
					:css({  ['text-align'] = 'right',
						color = '#FF0000',
						cursor = 'help',
						['border-bottom'] = '1px dashed',
						['font-weight'] = 'bold' })
					:wikitext('Error')
				:done()
			:done()
	elseif alt then
		local _coins = ' coin'..(price > 1 and 's' or '')
		ret	:tag('td')
				:attr('data-sort-value',vsort)
				:attr('title',commas(price).._coins..' each; this item has a distinct value, even though it cannot be traded on the Grand Exchange.')
				:css({ ['text-align'] = 'right',
					cursor = 'help' })
				:wikitext(total)
			:done()
	else
		ret	:tag('td')
				:attr('data-sort-value',vsort)
				:attr('title','This item cannot be traded on the Grand Exchange and has no applicable value to display.')
				:css({ ['text-align'] = 'right',
					cursor = 'help',
					color = '#999' })
				:wikitext('Not sold')
			:done()
	end
	
	if (profit ~= '-' and profit > 1) then
        ret :tag('td')
	        :attr('data-sort-value',vsort)
	        --:css({color = '#111' })
	        :attr('title', 'Profit made!')
	        :wikitext('[[File:' .. coins_image(profit) .. ']] ' .. profit)
        :done()
    elseif (profit ~= '-' and profit <= 0) then
        ret :tag('td')
	        :attr('data-sort-value',vsort)
	        :css({color = '#FF0000' })
	        :attr('title', 'Profit not made')
	        :wikitext('[[File:' .. coins_image(profit) .. ']] ' .. profit)
        :done()
    else
    	    ret :tag('td')
	        :attr('data-sort-value',vsort)
	        :css({color = '#ffff00' })
	        :attr('title', 'Untradeable')
	        :wikitext(profit)
        :done()
    end
	
	-- SMW
	local smw = ''
	if ns == '' and smwjson == true then
		smw = string.format('[[Drops item::%s| ]][[Drop JSON::&#123; "name": "%s", "quantity": &#91;%s,%s&#93;, "rarity": "%s" &#125;| ]]',
						name, name, _l or "'?'", _h or "'?'", _r)
	elseif ns == '' and smwjson == 'rdt' then
		smw = string.format('[[Drops item from RDT::%s| ]]',name)
	end
	return tostring(ret)..smw
end


function qty(price,quantity)
	-- if no quantity is given, return unknown and the price
	if not quantity or quantity == 'unknown' then
		return 'Unknown', price
	end
	-- en dashes are the proper dash for number ranges
	-- replace all hyphens and em dashes with en
	-- strip *all* whitespace
	-- change '(noted)' to '$n' for parsing
	quantity = mw.ustring.gsub(quantity,'[-—]','–')
		:gsub('%s','')
		:gsub('%(noted%)','$n')
	-- split list into table
	local vals = mw.text.split(quantity,'[,;]')
	-- All prices ranges will be a range
	-- e.g. if items valued at 100 coins are dropped in quantities of 1, 3, 5
	-- the price will be 100–500 rather than 100; 300; 500
	-- If low and high vars are the same in the end, only 1 price is displayed
	local low = 2147483648
	local high = 0
	-- recreate the quantity string to ensure consistent formatting
	local numstr = {}
	for i, v in ipairs(vals) do
		local clean = v:gsub('$n','')
		-- if list element contains an en dash (indicating range)
		-- Find the smaller/larger number (just in case)
		-- Compare them to the current min/max
		-- put them in order with desired format
		if mw.ustring.find(v,'–') then
			local splitvals = mw.text.split(clean,'–')
			-- assume a is smaller, b is larger
			local a = tonumber(splitvals[1])
			local b = tonumber(splitvals[2])
			-- Just in case
			if a > b then
				a,b = b,a
			end
			if a < low then
				low = a
			end
			if b > high then
				high = b
			end
			local addx = commas(a)..'–'..commas(b)
			if v:find('$n') then
				addx = addx.._noted
			end
			table.insert(numstr,addx)
		else
			local a = tonumber(clean)
			if a < low then
				low = a
			end
			if a > high then 
				high = a
			end
			local addx = commas(a)
			if v:find('$n') then
				addx = addx.._noted
			end
			table.insert(numstr,addx)
		end
	end
	-- Add a line break if there are too many elements
	-- To keep the tables thin
	if #numstr > 11 then
		local mid = math.floor(#numstr/2)
		numstr[mid] = '<br/>'..numstr[mid]
	end
	-- To prevent any possible confusion with formatted numbers
	-- elements should be separated with semicolons followed by a space
	numstr = table.concat(numstr,'; ')
	-- If no numbers are found in the string, return unknown
	if not numstr:find('%d') then
		return 'Unknown', price
	end

	local qtys

	if high == low then
		qtys = { high = high }
	else
		qtys = { low = low, high = high }
	end

	local priceret = get_price(price,qtys)

	-- highest val to also be used as a sort key
	local sort = 0
	if tonumber(price) then
		sort = high * tonumber(price)
	end

	return numstr, priceret, sort, high, low
end

-- function to parse the quantity ranges and give a price range
-- also returns the desired format
function get_price(price,quantity)
	local ttl
	if not price then
		ttl = 'Not sold'
	elseif not quantity.low then
		ttl = price * quantity.high
		ttl = commas(ttl)
	else
		local lower = price * quantity.low
		local higher = price * quantity.high
		ttl = commas(lower) .. '–' .. commas(higher)
	end
	return ttl
end

-- match -> category
-- pattern matching allowed
-- all lowercase
-- DO NOT INFLATE THIS TABLE
-- If a specific item does not fall into the category you want it to
-- then oh well
-- get over it
-- if items fall into a category they shouldn't, that's fine too
-- these aren't directly visible and are only used a rough sort
local sortnames = {
	runes = { ' rune$' },
	talismans = { 'talisman' },
	armour = { 'platebody', 'platelegs', 'plateskirt', 'helm', 'kiteshield', 'shield ', 'shield$', 'gloves', 'boots', 
			'chainbody', 'cape' },
	weapons = { 'axe', 'sword', 'staff', 'javelin', 'bow', 'hatchet', 'wand', 'spear', 'halberd', 'claw',
			'mace', 'warhammer', 'whip', 'dagger', 'throwing', 'dart', 'hasta', 'scimitar' },
	ammunition = { 'arrow', 'bolt' },
	logs = { 'logs' },
	herbs = { 'grimy', '^clean' },
	seeds = { 'seed', 'spore' },
	ores = { ' ore$', 'coal' },
	bars = { ' bar$' },
	gems = { 'uncut' },
	raw = { '^raw' },
	potions = { '%([1-4]%)$' }, -- this might match too much, but whatever

	-- Sorting of common items to consistent places
	-- sort rare drop table to back
	zzz = { 'rare drop table' },
	-- sort coins to front
	['!!!'] = { '^coins' },
}

-- adds a category in front of the name to give it a slightly improved sorting function
function namesort(arg,rarg)
	local arg = string.lower(arg or '')
	local cat = '!other' -- "!" to keep in front

	for w, v in pairs(sortnames) do
		for _, x in ipairs(v) do
			if mw.ustring.match(arg,x) then
				cat = w
				break
			end
		end
	end

	return string.format('%s %s %s',cat,rarg,arg)
end

-- adding categories to mainspace
function categories(...)
	local name,quantity,rarity = unpack(...)
	local ret = ''
	name = name:lower()
	quantity = quantity:lower()
	if name:find('effigy') then
		ret = ret .. '[[Category:Effigy dropping monsters]]'
	elseif name:find('clue scroll') then
		ret = ret .. '[[Category:Clue scroll dropping monsters]]'
	elseif name:find('rare drop table') then
		ret = ret .. '[[Category:Monsters with access to the rare drop table]]'
	end
	if not rarities[rarity:lower()] then
		ret = ret .. '[[Category:Needs drop rarity added]]'
	end
	if quantity:find('unknown') then
		ret = ret .. '[[Category:Needs drop quantity added]]'
	end
	return ret
end

return p